Merge pull request #9284 from gladiac1337/feature-haproxy-v2.0.0
authorDaniel Engberg <daniel.engberg.lists@pyret.net>
Fri, 21 Jun 2019 21:00:04 +0000 (23:00 +0200)
committerGitHub <noreply@github.com>
Fri, 21 Jun 2019 21:00:04 +0000 (23:00 +0200)
haproxy: Update HAProxy to v2.0.0 (LTS)

27 files changed:
net/haproxy/Makefile
net/haproxy/files/haproxy.cfg
net/haproxy/files/haproxy.hotplug
net/haproxy/files/haproxy.init
net/haproxy/get-latest-patches.sh
net/haproxy/patches/000-BUG-MEDIUM-h2-htx-Update-data-length-of-the-HTX-when-the-cookie-list-is-built.patch [new file with mode: 0644]
net/haproxy/patches/000-BUG-MINOR-http-Call-stream_inc_be_http_req_ctr-only-one-time-per-request.patch [deleted file]
net/haproxy/patches/001-BUG-MEDIUM-spoe-arg-len-encoded-in-previous-frag-frame-but-len-changed.patch [deleted file]
net/haproxy/patches/001-BUG-MINOR-lua-htx-Make-txn-req_req_-and-txn-res_rep_-HTX-aware.patch [new file with mode: 0644]
net/haproxy/patches/002-BUG-MINOR-mux-h1-Add-the-header-connection-in-lower-case-in-outgoing-messages.patch [new file with mode: 0644]
net/haproxy/patches/002-MINOR-spoe-Use-the-sample-context-to-pass-frag_ctx-info-during-encoding.patch [deleted file]
net/haproxy/patches/003-BUG-MEDIUM-compression-Set-Vary-Accept-Encoding-for-compressed-responses.patch [new file with mode: 0644]
net/haproxy/patches/003-DOC-contrib-modsecurity-Typos-and-fix-the-reject-example.patch [deleted file]
net/haproxy/patches/004-BUG-MEDIUM-contrib-modsecurity-If-host-header-is-NULL-dont-try-to-strdup-it.patch [deleted file]
net/haproxy/patches/004-MINOR-htx-Add-the-function-htx_change_blk_value_len.patch [new file with mode: 0644]
net/haproxy/patches/005-BUG-MEDIUM-htx-Fully-update-HTX-message-when-the-block-value-is-changed.patch [new file with mode: 0644]
net/haproxy/patches/005-MINOR-examples-Use-right-locale-for-the-last-changelog-date-in-haproxy-spec.patch [deleted file]
net/haproxy/patches/006-BUG-MAJOR-map-acl-real-fix-segfault-during-show-map-acl-on-CLI.patch [deleted file]
net/haproxy/patches/006-BUG-MEDIUM-mux-h2-Reset-padlen-when-several-frames-are-demux.patch [new file with mode: 0644]
net/haproxy/patches/007-BUG-MEDIUM-listener-Fix-how-unlimited-number-of-consecutive-accepts-is-handled.patch [deleted file]
net/haproxy/patches/007-BUG-MEDIUM-mux-h2-Remove-the-padding-length-when-a-DATA-frame-size-is-checked.patch [new file with mode: 0644]
net/haproxy/patches/008-BUG-MEDIUM-lb_fwlc-Dont-test-the-servers-lb_tree-from-outside-the-lock.patch [new file with mode: 0644]
net/haproxy/patches/008-MINOR-config-Test-validity-of-tune-maxaccept-during-the-config-parsing.patch [deleted file]
net/haproxy/patches/009-CLEANUP-config-Dont-alter-listener--maxaccept-when-nbproc-is-set-to-1.patch [deleted file]
net/haproxy/patches/010-MINOR-threads-Implement-HA_ATOMIC_LOAD.patch [deleted file]
net/haproxy/patches/011-BUG-MEDIUM-port_range-Make-the-ring-buffer-lock-free.patch [deleted file]
net/haproxy/patches/012-deprecated-openssl.patch [deleted file]

index b42bc595831d6aabfb693dca5f61692df57d0d95..4047f08904135af791606bf144e4af3492e8ce90 100644 (file)
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=haproxy
-PKG_VERSION:=1.8.20
+PKG_VERSION:=2.0.0
 PKG_RELEASE:=1
 
 PKG_SOURCE:=haproxy-$(PKG_VERSION).tar.gz
-PKG_SOURCE_URL:=https://www.haproxy.org/download/1.8/src/
-PKG_HASH:=3228f78d5fe1dfbaccf41bf387e36b08eeef6e16330053cafde5fa303e262b16
+PKG_SOURCE_URL:=https://www.haproxy.org/download/2.0/src/
+PKG_HASH:=fe0a0d69e1091066a91b8d39199c19af8748e0e872961c6fc43c91ec7a28ff20
 
 PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(BUILD_VARIANT)/$(PKG_NAME)-$(PKG_VERSION)
 PKG_LICENSE:=GPL-2.0
@@ -94,7 +94,7 @@ ifeq ($(CONFIG_TARGET_x86),y)
   ENABLE_REGPARM:=y
 endif
 
-LINUX_TARGET:=linux2628
+LINUX_TARGET:=linux-glibc
 
 ifeq ($(BUILD_VARIANT),ssl)
        ADDON+=USE_OPENSSL=1
@@ -133,14 +133,16 @@ define Build/Compile
                CC="$(TARGET_CC)" \
                PCREDIR="$(STAGING_DIR)/usr/" \
                SMALL_OPTS="-DBUFSIZE=16384 -DMAXREWRITE=1030 -DSYSTEM_MAXCONN=165530" \
-               USE_LINUX_TPROXY=1 USE_LINUX_SPLICE=1 USE_TFO=1 \
-               USE_ZLIB=yes USE_PCRE=1 USE_PCRE_JIT=1 USE_GETADDRINFO=1 \
+               USE_LINUX_TPROXY=1 USE_LINUX_SPLICE=1 USE_TFO=1 USE_NS=1 \
+               USE_ZLIB=1 USE_PCRE=1 USE_PCRE_JIT=1 USE_GETADDRINFO=1 \
+               USE_THREAD=1 USE_PTHREAD_PSHARED=1 \
                VERSION="$(PKG_VERSION)" SUBVERS="-$(PKG_RELEASE)" \
                VERDATE="$(shell date -d @$(SOURCE_DATE_EPOCH) '+%Y/%m/%d')" IGNOREGIT=1 \
                $(ADDON) \
-               CFLAGS="$(TARGET_CFLAGS)" \
+               CFLAGS="$(TARGET_CFLAGS) -fno-strict-aliasing -Wdeclaration-after-statement -fwrapv -Wno-format-truncation -Wno-unused-label -Wno-sign-compare -Wno-unused-parameter -Wno-old-style-declaration -Wno-ignored-qualifiers -Wno-clobbered -Wno-missing-field-initializers -Wno-implicit-fallthrough -Wno-stringop-overflow -Wtype-limits -Wshift-negative-value -Wshift-overflow=2 -Wduplicated-cond -Wnull-dereference" \
                LD="$(TARGET_CC)" \
-               LDFLAGS="$(TARGET_LDFLAGS) -latomic"
+               LDFLAGS="$(TARGET_LDFLAGS) -latomic" \
+               EXTRA_OBJS="contrib/prometheus-exporter/service-prometheus.o"
 
        $(MAKE_VARS) $(MAKE) -C $(PKG_BUILD_DIR) \
                DESTDIR="$(PKG_INSTALL_DIR)" \
@@ -152,6 +154,7 @@ define Build/Compile
        $(MAKE_VARS) $(MAKE) -C $(PKG_BUILD_DIR)/contrib/halog \
                DESTDIR="$(PKG_INSTALL_DIR)" \
                $(MAKE_FLAGS) \
+               OPTIMIZE="$(TARGET_CFLAGS)" \
                ADDLIB="-lcrypto" \
                halog
 endef
index a54f5f5ddb67f9cb272d2e28a4d95151b372ef91..ffe5949ca015c24b37df9ec4f986753939d6d020 100644 (file)
@@ -1,6 +1,6 @@
-# Example configuration file for HAProxy 1.3, refer to the url below for
+# Example configuration file for HAProxy 2.0, refer to the url below for
 # a full documentation and examples for configuration:
-# http://haproxy.1wt.eu/download/1.3/doc/configuration.txt
+# https://cbonte.github.io/haproxy-dconv/2.0/configuration.html
 
 
 # Global parameters
@@ -38,6 +38,13 @@ global
        # limits like number of open file descriptors. Default is 1.
        #nbproc 2
 
+# Default parameters
+defaults
+       # Default timeouts
+       timeout connect 5000ms
+       timeout client 50000ms
+       timeout server 50000ms
+
 
 # Example HTTP proxy listener
 listen my_http_proxy
@@ -78,9 +85,9 @@ listen my_smtp_proxy
        # Round robin load balancing over two servers on port 123 forcing
        # the address 192.168.1.1 and port 25 as source.
        balance roundrobin
-  #use next line for transparent proxy, so the servers can see the 
-  #original ip-address and remove source keyword in server definition
-  #source 0.0.0.0 usesrc clientip
+       #use next line for transparent proxy, so the servers can see the 
+       #original ip-address and remove source keyword in server definition
+       #source 0.0.0.0 usesrc clientip
        server server01 192.168.1.10:123 source 192.168.1.1:25
        server server02 192.168.1.20:123 source 192.168.1.1:25
        
index d14b5bf3f4d27659259b554b1551b110918bdbf3..bfb5d6da122fb68755c3a2ec40379225cdc93851 100644 (file)
@@ -1,7 +1,6 @@
 #!/bin/sh
 
 if [ "$ACTION" = add ]; then
-
        /etc/init.d/haproxy enabled && \
                /etc/init.d/haproxy start
 fi
index edda9a3a783e209834295ab3283819bf70e16707..52bc126ac2d1b8a5bd101ddf43d5db078a041763 100644 (file)
@@ -5,6 +5,7 @@ START=99
 STOP=80
 
 SERVICE_USE_PID=1
+EXTRA_COMMANDS="check"
 
 HAPROXY_BIN="/usr/sbin/haproxy"
 HAPROXY_CONFIG="/etc/haproxy.cfg"
@@ -20,6 +21,9 @@ stop() {
 }
 
 reload() {
-       $HAPROXY_BIN -D -q -f $HAPROXY_CONFIG -p $HAPROXY_PID -sf $(cat $HAPROXY_PID | tr "\n" " ")     
-       #$HAPROXY_BIN -D -q -f $HAPROXY_CONFIG -p $HAPROXY_PID -sf $(cat $HAPROXY_PID)
+       $HAPROXY_BIN -D -q -f $HAPROXY_CONFIG -p $HAPROXY_PID -sf $(cat $HAPROXY_PID)
+}
+
+check() {
+        $HAPROXY_BIN -c -q -V -f $HAPROXY_CONFIG
 }
index f4b683ecf0d3c3ba25a55c4ff8d85fe0094b2e1d..a60529e64d591cb2182d153a8c978170611369dd 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/bash
 
-CLONEURL=http://git.haproxy.org/git/haproxy-1.8.git
-BASE_TAG=v1.8.20
+CLONEURL=http://git.haproxy.org/git/haproxy-2.0.git
+BASE_TAG=v2.0.0
 TMP_REPODIR=tmprepo
 PATCHESDIR=patches
 
diff --git a/net/haproxy/patches/000-BUG-MEDIUM-h2-htx-Update-data-length-of-the-HTX-when-the-cookie-list-is-built.patch b/net/haproxy/patches/000-BUG-MEDIUM-h2-htx-Update-data-length-of-the-HTX-when-the-cookie-list-is-built.patch
new file mode 100644 (file)
index 0000000..6d79bf8
--- /dev/null
@@ -0,0 +1,32 @@
+commit 032cff38c24d8359dc575423a94d19b6ad8bf848
+Author: Christopher Faulet <cfaulet@haproxy.com>
+Date:   Mon Jun 17 11:44:47 2019 +0200
+
+    BUG/MEDIUM: h2/htx: Update data length of the HTX when the cookie list is built
+    
+    When an H2 request is converted into an HTX message, All cookie headers are
+    grouped into one, each value separated by a semicolon (;). To do so, we add the
+    header "cookie" with the first value and then we update the value by appending
+    other cookies. But during this operation, only the size of the HTX block is
+    updated. And not the data length of the whole HTX message.
+    
+    It is an old bug and it seems to work by chance till now. But it may lead to
+    undefined behaviour by time to time.
+    
+    This patch must be backported to 2.0 and 1.9
+    
+    (cherry picked from commit 0c6de00d7c842a682bba7586ef34fb10f69ec63c)
+    Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
+
+diff --git a/src/h2.c b/src/h2.c
+index 9681aca5..32c1ef16 100644
+--- a/src/h2.c
++++ b/src/h2.c
+@@ -737,6 +737,7 @@ int h2_make_htx_request(struct http_hdr *list, struct htx *htx, unsigned int *ms
+                               goto fail;
+                       htx_set_blk_value_len(blk, tl);
++                      htx->data += vl+2;
+                       *(char *)(htx_get_blk_ptr(htx, blk) + bs + 0) = ';';
+                       *(char *)(htx_get_blk_ptr(htx, blk) + bs + 1) = ' ';
+                       memcpy(htx_get_blk_ptr(htx, blk) + bs + 2, list[ck].v.ptr, vl);
diff --git a/net/haproxy/patches/000-BUG-MINOR-http-Call-stream_inc_be_http_req_ctr-only-one-time-per-request.patch b/net/haproxy/patches/000-BUG-MINOR-http-Call-stream_inc_be_http_req_ctr-only-one-time-per-request.patch
deleted file mode 100644 (file)
index 4449df1..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-commit cf2f1243373be97249567ffd259e975cc87068b8
-Author: Christopher Faulet <cfaulet@haproxy.com>
-Date:   Mon Apr 29 13:12:02 2019 +0200
-
-    BUG/MINOR: http: Call stream_inc_be_http_req_ctr() only one time per request
-    
-    The function stream_inc_be_http_req_ctr() is called at the beginning of the
-    analysers AN_REQ_HTTP_PROCESS_FE/BE. It as an effect only on the backend. But we
-    must be careful to call it only once. If the processing of HTTP rules is
-    interrupted in the middle, when the analyser is resumed, we must not call it
-    again. Otherwise, the tracked counters of the backend are incremented several
-    times.
-    
-    This bug was reported in github. See issue #74.
-    
-    This fix should be backported as far as 1.6.
-    
-    (cherry picked from commit 1907ccc2f75b78ace1ee4acdfc60d48a76e3decd)
-    Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
-    (cherry picked from commit 319921866ea9ecc46215fea5679abc8efdfcbea5)
-    [cf: HTX part was removed]
-    Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
-
-diff --git a/src/proto_http.c b/src/proto_http.c
-index ccacd6a4..556cabad 100644
---- a/src/proto_http.c
-+++ b/src/proto_http.c
-@@ -3420,8 +3420,10 @@ int http_process_req_common(struct stream *s, struct channel *req, int an_bit, s
-               req->buf->i,
-               req->analysers);
--      /* just in case we have some per-backend tracking */
--      stream_inc_be_http_req_ctr(s);
-+      /* just in case we have some per-backend tracking. Only called the first
-+       * execution of the analyser. */
-+      if (!s->current_rule || s->current_rule_list != &px->http_req_rules)
-+              stream_inc_be_http_req_ctr(s);
-       /* evaluate http-request rules */
-       if (!LIST_ISEMPTY(&px->http_req_rules)) {
diff --git a/net/haproxy/patches/001-BUG-MEDIUM-spoe-arg-len-encoded-in-previous-frag-frame-but-len-changed.patch b/net/haproxy/patches/001-BUG-MEDIUM-spoe-arg-len-encoded-in-previous-frag-frame-but-len-changed.patch
deleted file mode 100644 (file)
index 9ef9507..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-commit c1620a52a3def02b4837376385c416c03ca874c4
-Author: Kevin Zhu <ipandtcp@gmail.com>
-Date:   Fri Apr 26 14:00:01 2019 +0800
-
-    BUG/MEDIUM: spoe: arg len encoded in previous frag frame but len changed
-    
-    Fragmented arg will do fetch at every encode time, each fetch may get
-    different result if SMP_F_MAY_CHANGE, for example res.payload, but
-    the length already encoded in first fragment of the frame, that will
-    cause SPOA decode failed and waste resources.
-    
-    This patch must be backported to 1.9 and 1.8.
-    
-    (cherry picked from commit f7f54280c8106e92a55243f5d60f8587e79602d1)
-    Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
-    (cherry picked from commit 3a838e526cdbc00ded5362e66f1ef3a441abc3c1)
-    Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
-
-diff --git a/include/proto/spoe.h b/include/proto/spoe.h
-index 002cf7d7..2cdca10b 100644
---- a/include/proto/spoe.h
-+++ b/include/proto/spoe.h
-@@ -121,7 +121,7 @@ spoe_decode_buffer(char **buf, char *end, char **str, uint64_t *len)
-  * many bytes has been encoded. If <*off> is zero at the end, it means that all
-  * data has been encoded. */
- static inline int
--spoe_encode_data(struct sample *smp, unsigned int *off, char **buf, char *end)
-+spoe_encode_data(unsigned int *len, struct sample *smp, unsigned int *off, char **buf, char *end)
- {
-       char *p = *buf;
-       int   ret;
-@@ -183,15 +183,16 @@ spoe_encode_data(struct sample *smp, unsigned int *off, char **buf, char *end)
-                               ret = spoe_encode_frag_buffer(chk->str, chk->len, &p, end);
-                               if (ret == -1)
-                                       return -1;
-+                              *len = chk->len;
-                       }
-                       else {
-                               /* The sample has been fragmented, encode remaining data */
--                              ret = MIN(chk->len - *off, end - p);
-+                              ret = MIN(*len - *off, end - p);
-                               memcpy(p, chk->str + *off, ret);
-                               p += ret;
-                       }
-                       /* Now update <*off> */
--                      if (ret + *off != chk->len)
-+                      if (ret + *off != *len)
-                               *off += ret;
-                       else
-                               *off = 0;
-diff --git a/include/types/spoe.h b/include/types/spoe.h
-index 53e7200c..cfaa42f8 100644
---- a/include/types/spoe.h
-+++ b/include/types/spoe.h
-@@ -304,6 +304,7 @@ struct spoe_context {
-               struct spoe_message *curmsg;      /* SPOE message from which to resume encoding */
-               struct spoe_arg     *curarg;      /* SPOE arg in <curmsg> from which to resume encoding */
-               unsigned int         curoff;      /* offset in <curarg> from which to resume encoding */
-+              unsigned int         curlen;      /* length of <curarg> need to be encode, for SMP_F_MAY_CHANGE data */
-               unsigned int         flags;       /* SPOE_FRM_FL_* */
-       } frag_ctx; /* Info about fragmented frames, valid on if SPOE_CTX_FL_FRAGMENTED is set */
- };
-diff --git a/src/flt_spoe.c b/src/flt_spoe.c
-index f6109778..0c0b3794 100644
---- a/src/flt_spoe.c
-+++ b/src/flt_spoe.c
-@@ -2172,6 +2172,7 @@ spoe_encode_message(struct stream *s, struct spoe_context *ctx,
-       list_for_each_entry(arg, &msg->args, list) {
-               ctx->frag_ctx.curarg = arg;
-               ctx->frag_ctx.curoff = UINT_MAX;
-+              ctx->frag_ctx.curlen = 0;
-         encode_argument:
-               if (ctx->frag_ctx.curoff != UINT_MAX)
-@@ -2186,7 +2187,7 @@ spoe_encode_message(struct stream *s, struct spoe_context *ctx,
-               /* Fetch the arguement value */
-               smp = sample_process(s->be, s->sess, s, dir|SMP_OPT_FINAL, arg->expr, NULL);
--              ret = spoe_encode_data(smp, &ctx->frag_ctx.curoff, buf, end);
-+              ret = spoe_encode_data(&ctx->frag_ctx.curlen, smp, &ctx->frag_ctx.curoff, buf, end);
-               if (ret == -1 || ctx->frag_ctx.curoff)
-                       goto too_big;
-       }
diff --git a/net/haproxy/patches/001-BUG-MINOR-lua-htx-Make-txn-req_req_-and-txn-res_rep_-HTX-aware.patch b/net/haproxy/patches/001-BUG-MINOR-lua-htx-Make-txn-req_req_-and-txn-res_rep_-HTX-aware.patch
new file mode 100644 (file)
index 0000000..693dd64
--- /dev/null
@@ -0,0 +1,32 @@
+commit 5a8549e68225070d0b79cbbb9c5f791e103685e7
+Author: Christopher Faulet <cfaulet@haproxy.com>
+Date:   Mon Jun 17 13:36:06 2019 +0200
+
+    BUG/MINOR: lua/htx: Make txn.req_req_* and txn.res_rep_* HTX aware
+    
+    These bindings were not updated to support HTX streams.
+    
+    This patch must be backported to 2.0 and 1.9. It fixes the issue #124.
+    
+    (cherry picked from commit ea418748dd22331e9798cfd8f5e25b436cd577e3)
+    Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
+
+diff --git a/src/hlua.c b/src/hlua.c
+index 28abd083..32f0e8db 100644
+--- a/src/hlua.c
++++ b/src/hlua.c
+@@ -5375,7 +5375,13 @@ __LJMP static inline int hlua_http_rep_hdr(lua_State *L, struct hlua_txn *htxn,
+       if (!(re = regex_comp(reg, 1, 1, NULL)))
+               WILL_LJMP(luaL_argerror(L, 3, "invalid regex"));
+-      http_transform_header_str(htxn->s, msg, name, name_len, value, re, action);
++      if (IS_HTX_STRM(htxn->s)) {
++              struct htx *htx = htxbuf(&msg->chn->buf);
++
++              htx_transform_header_str(htxn->s, msg->chn, htx, ist2(name, name_len), value, re, action);
++      }
++      else
++              http_transform_header_str(htxn->s, msg, name, name_len, value, re, action);
+       regex_free(re);
+       return 0;
+ }
diff --git a/net/haproxy/patches/002-BUG-MINOR-mux-h1-Add-the-header-connection-in-lower-case-in-outgoing-messages.patch b/net/haproxy/patches/002-BUG-MINOR-mux-h1-Add-the-header-connection-in-lower-case-in-outgoing-messages.patch
new file mode 100644 (file)
index 0000000..73983b4
--- /dev/null
@@ -0,0 +1,29 @@
+commit 661bfc3d0e1b7756db59d00d86e316f694cae3c6
+Author: Christopher Faulet <cfaulet@haproxy.com>
+Date:   Mon Jun 17 14:07:46 2019 +0200
+
+    BUG/MINOR: mux-h1: Add the header connection in lower case in outgoing messages
+    
+    When necessary, this header is directly added in outgoing messages by the H1
+    multiplexer. Because there is no HTX conversion first, the header name is not
+    converserted to its lower case version. So, it must be added in lower case by
+    the multiplexer.
+    
+    This patch must be backported to 2.0 and 1.9.
+    
+    (cherry picked from commit a110ecbd843e156dd01c6ac581c735be5e240d5b)
+    Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
+
+diff --git a/src/mux_h1.c b/src/mux_h1.c
+index 317f1a55..21deb354 100644
+--- a/src/mux_h1.c
++++ b/src/mux_h1.c
+@@ -1642,7 +1642,7 @@ static size_t h1_process_output(struct h1c *h1c, struct buffer *buf, size_t coun
+                                       /* There is no "Connection:" header and
+                                        * it the conn_mode must be
+                                        * processed. So do it */
+-                                      n = ist("Connection");
++                                      n = ist("connection");
+                                       v = ist("");
+                                       h1_process_output_conn_mode(h1s, h1m, &v);
+                                       if (v.len) {
diff --git a/net/haproxy/patches/002-MINOR-spoe-Use-the-sample-context-to-pass-frag_ctx-info-during-encoding.patch b/net/haproxy/patches/002-MINOR-spoe-Use-the-sample-context-to-pass-frag_ctx-info-during-encoding.patch
deleted file mode 100644 (file)
index c26629c..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-commit 72fdff1fdb5b82685dc3d2db23ece042195a0cbd
-Author: Christopher Faulet <cfaulet@haproxy.com>
-Date:   Fri Apr 26 14:30:15 2019 +0200
-
-    MINOR: spoe: Use the sample context to pass frag_ctx info during encoding
-    
-    This simplifies the API and hide the details in the sample. This way, only
-    string and binary are aware of these info, because other types cannot be
-    partially encoded.
-    
-    This patch may be backported to 1.9 and 1.8.
-    
-    (cherry picked from commit 85db3212b87b33f1a39a688546f4f53a5c4ba4da)
-    Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
-    (cherry picked from commit b93366e3ee44f5de93f01569fcdcd602f6d0703f)
-    Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
-
-diff --git a/include/proto/spoe.h b/include/proto/spoe.h
-index 2cdca10b..cce13e50 100644
---- a/include/proto/spoe.h
-+++ b/include/proto/spoe.h
-@@ -117,11 +117,9 @@ spoe_decode_buffer(char **buf, char *end, char **str, uint64_t *len)
-  *
-  * If the value is too big to be encoded, depending on its type, then encoding
-  * failed or the value is partially encoded. Only strings and binaries can be
-- * partially encoded. In this case, the offset <*off> is updated to known how
-- * many bytes has been encoded. If <*off> is zero at the end, it means that all
-- * data has been encoded. */
-+ * partially encoded. */
- static inline int
--spoe_encode_data(unsigned int *len, struct sample *smp, unsigned int *off, char **buf, char *end)
-+spoe_encode_data(struct sample *smp, char **buf, char *end)
- {
-       char *p = *buf;
-       int   ret;
-@@ -164,12 +162,16 @@ spoe_encode_data(unsigned int *len, struct sample *smp, unsigned int *off, char
-               case SMP_T_STR:
-               case SMP_T_BIN: {
-+                      /* If defined, get length and offset of the sample by reading the sample
-+                       * context. ctx.a[0] is the pointer to the length and ctx.a[1] is the
-+                       * pointer to the offset. If the offset is greater than 0, it means the
-+                       * sample is partially encoded. In this case, we only need to encode the
-+                       * reamining. When all the sample is encoded, the offset is reset to 0.
-+                       * So the caller know it can try to encode the next sample. */
-                       struct chunk *chk = &smp->data.u.str;
-+                      unsigned int *len  = (smp->ctx.a[0] ? smp->ctx.a[0] : 0);
-+                      unsigned int *off  = (smp->ctx.a[1] ? smp->ctx.a[1] : 0);
--                      /* Here, we need to know if the sample has already been
--                       * partially encoded. If yes, we only need to encode the
--                       * remaining, <*off> reprensenting the number of bytes
--                       * already encoded. */
-                       if (!*off) {
-                               /* First evaluation of the sample : encode the
-                                * type (string or binary), the buffer length
-diff --git a/src/flt_spoe.c b/src/flt_spoe.c
-index 0c0b3794..66d8b045 100644
---- a/src/flt_spoe.c
-+++ b/src/flt_spoe.c
-@@ -2187,7 +2187,9 @@ spoe_encode_message(struct stream *s, struct spoe_context *ctx,
-               /* Fetch the arguement value */
-               smp = sample_process(s->be, s->sess, s, dir|SMP_OPT_FINAL, arg->expr, NULL);
--              ret = spoe_encode_data(&ctx->frag_ctx.curlen, smp, &ctx->frag_ctx.curoff, buf, end);
-+              smp->ctx.a[0] = &ctx->frag_ctx.curlen;
-+              smp->ctx.a[1] = &ctx->frag_ctx.curoff;
-+              ret = spoe_encode_data(smp, buf, end);
-               if (ret == -1 || ctx->frag_ctx.curoff)
-                       goto too_big;
-       }
diff --git a/net/haproxy/patches/003-BUG-MEDIUM-compression-Set-Vary-Accept-Encoding-for-compressed-responses.patch b/net/haproxy/patches/003-BUG-MEDIUM-compression-Set-Vary-Accept-Encoding-for-compressed-responses.patch
new file mode 100644 (file)
index 0000000..b71741c
--- /dev/null
@@ -0,0 +1,253 @@
+commit eaf650083924a697cde3379703984c5e7a5ebd41
+Author: Tim Duesterhus <tim@bastelstu.be>
+Date:   Mon Jun 17 16:10:07 2019 +0200
+
+    BUG/MEDIUM: compression: Set Vary: Accept-Encoding for compressed responses
+    
+    Make HAProxy set the `Vary: Accept-Encoding` response header if it compressed
+    the server response.
+    
+    Technically the `Vary` header SHOULD also be set for responses that would
+    normally be compressed based off the current configuration, but are not due
+    to a missing or invalid `Accept-Encoding` request header or due to the
+    maximum compression rate being exceeded.
+    
+    Not setting the header in these cases does no real harm, though: An
+    uncompressed response might be returned by a Cache, even if a compressed
+    one could be retrieved from HAProxy. This increases the traffic to the end
+    user if the cache is unable to compress itself, but it saves another
+    roundtrip to HAProxy.
+    
+    see the discussion on the mailing list: https://www.mail-archive.com/haproxy@formilux.org/msg34221.html
+    Message-ID: 20190617121708.GA2964@1wt.eu
+    
+    A small issue remains: The User-Agent is not added to the `Vary` header,
+    despite being relevant to the response. Adding the User-Agent header would
+    make responses effectively uncacheable and it's unlikely to see a Mozilla/4
+    in the wild in 2019.
+    
+    Add a reg-test to ensure the behaviour as described in this commit message.
+    
+    see issue #121
+    Should be backported to all branches with compression (i.e. 1.6+).
+    
+    (cherry picked from commit 721d686bd10dc6993859f9026ad907753d1d2064)
+    Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
+
+diff --git a/reg-tests/compression/vary.vtc b/reg-tests/compression/vary.vtc
+new file mode 100644
+index 00000000..0a060e4b
+--- /dev/null
++++ b/reg-tests/compression/vary.vtc
+@@ -0,0 +1,187 @@
++varnishtest "Compression sets Vary header"
++
++#REQUIRE_VERSION=1.9
++#REQUIRE_OPTION=ZLIB|SLZ
++
++feature ignore_unknown_macro
++
++server s1 {
++        rxreq
++        expect req.url == "/plain/accept-encoding-gzip"
++        expect req.http.accept-encoding == "gzip"
++        txresp \
++          -hdr "Content-Type: text/plain" \
++          -bodylen 100
++
++        rxreq
++        expect req.url == "/plain/accept-encoding-invalid"
++        expect req.http.accept-encoding == "invalid"
++        txresp \
++          -hdr "Content-Type: text/plain" \
++          -bodylen 100
++
++        rxreq
++        expect req.url == "/plain/accept-encoding-null"
++        expect req.http.accept-encoding == "<undef>"
++        txresp \
++          -hdr "Content-Type: text/plain" \
++          -bodylen 100
++
++        rxreq
++        expect req.url == "/html/accept-encoding-gzip"
++        expect req.http.accept-encoding == "gzip"
++        txresp \
++          -hdr "Content-Type: text/html" \
++          -bodylen 100
++
++        rxreq
++        expect req.url == "/html/accept-encoding-invalid"
++        expect req.http.accept-encoding == "invalid"
++        txresp \
++          -hdr "Content-Type: text/html" \
++          -bodylen 100
++
++
++        rxreq
++        expect req.url == "/html/accept-encoding-null"
++        expect req.http.accept-encoding == "<undef>"
++        txresp \
++          -hdr "Content-Type: text/html" \
++          -bodylen 100
++
++        rxreq
++        expect req.url == "/dup-etag/accept-encoding-gzip"
++        expect req.http.accept-encoding == "gzip"
++        txresp \
++          -hdr "Content-Type: text/plain" \
++          -hdr "ETag: \"123\"" \
++          -hdr "ETag: \"123\"" \
++          -bodylen 100
++} -repeat 2 -start
++
++
++haproxy h1 -conf {
++    defaults
++        mode http
++        ${no-htx} option http-use-htx
++        timeout connect 1s
++        timeout client  1s
++        timeout server  1s
++
++    frontend fe-gzip
++        bind "fd@${fe_gzip}"
++        default_backend be-gzip
++
++    backend be-gzip
++        compression algo gzip
++        compression type text/plain
++        server www ${s1_addr}:${s1_port}
++
++    frontend fe-nothing
++        bind "fd@${fe_nothing}"
++        default_backend be-nothing
++
++    backend be-nothing
++        server www ${s1_addr}:${s1_port}
++} -start
++
++client c1 -connect ${h1_fe_gzip_sock} {
++        txreq -url "/plain/accept-encoding-gzip" \
++          -hdr "Accept-Encoding: gzip"
++        rxresp
++        expect resp.status == 200
++        expect resp.http.content-encoding == "gzip"
++        expect resp.http.vary == "Accept-Encoding"
++        gunzip
++        expect resp.bodylen == 100
++
++        txreq -url "/plain/accept-encoding-invalid" \
++          -hdr "Accept-Encoding: invalid"
++        rxresp
++        expect resp.status == 200
++        expect resp.http.vary == "<undef>"
++        expect resp.bodylen == 100
++
++        txreq -url "/plain/accept-encoding-null"
++        rxresp
++        expect resp.status == 200
++        expect resp.http.vary == "<undef>"
++        expect resp.bodylen == 100
++
++        txreq -url "/html/accept-encoding-gzip" \
++          -hdr "Accept-Encoding: gzip"
++        rxresp
++        expect resp.status == 200
++        expect resp.http.vary == "<undef>"
++        expect resp.bodylen == 100
++
++        txreq -url "/html/accept-encoding-invalid" \
++          -hdr "Accept-Encoding: invalid"
++        rxresp
++        expect resp.status == 200
++        expect resp.http.vary == "<undef>"
++        expect resp.bodylen == 100
++
++        txreq -url "/html/accept-encoding-null"
++        rxresp
++        expect resp.status == 200
++        expect resp.http.vary == "<undef>"
++        expect resp.bodylen == 100
++
++        txreq -url "/dup-etag/accept-encoding-gzip" \
++          -hdr "Accept-Encoding: gzip"
++        rxresp
++        expect resp.status == 200
++        expect resp.http.vary == "<undef>"
++        expect resp.bodylen == 100
++} -run
++
++# This Client duplicates c1, against the "nothing" frontend, ensuring no Vary header is ever set.
++client c2 -connect ${h1_fe_nothing_sock} {
++        txreq -url "/plain/accept-encoding-gzip" \
++          -hdr "Accept-Encoding: gzip"
++        rxresp
++        expect resp.status == 200
++        expect resp.http.vary == "<undef>"
++        expect resp.bodylen == 100
++
++        txreq -url "/plain/accept-encoding-invalid" \
++          -hdr "Accept-Encoding: invalid"
++        rxresp
++        expect resp.status == 200
++        expect resp.http.vary == "<undef>"
++        expect resp.bodylen == 100
++
++        txreq -url "/plain/accept-encoding-null"
++        rxresp
++        expect resp.status == 200
++        expect resp.http.vary == "<undef>"
++        expect resp.bodylen == 100
++
++        txreq -url "/html/accept-encoding-gzip" \
++          -hdr "Accept-Encoding: gzip"
++        rxresp
++        expect resp.status == 200
++        expect resp.http.vary == "<undef>"
++        expect resp.bodylen == 100
++
++        txreq -url "/html/accept-encoding-invalid" \
++          -hdr "Accept-Encoding: invalid"
++        rxresp
++        expect resp.status == 200
++        expect resp.http.vary == "<undef>"
++        expect resp.bodylen == 100
++
++        txreq -url "/html/accept-encoding-null"
++        rxresp
++        expect resp.status == 200
++        expect resp.http.vary == "<undef>"
++        expect resp.bodylen == 100
++
++        txreq -url "/dup-etag/accept-encoding-gzip" \
++          -hdr "Accept-Encoding: gzip"
++        rxresp
++        expect resp.status == 200
++        expect resp.http.vary == "<undef>"
++        expect resp.bodylen == 100
++} -run
+diff --git a/src/flt_http_comp.c b/src/flt_http_comp.c
+index b04dcd14..37f237fe 100644
+--- a/src/flt_http_comp.c
++++ b/src/flt_http_comp.c
+@@ -523,6 +523,9 @@ http_set_comp_reshdr(struct comp_state *st, struct stream *s, struct http_msg *m
+               }
+       }
++      if (http_header_add_tail2(msg, &txn->hdr_idx, "Vary: Accept-Encoding", 21) < 0)
++              goto error;
++
+       return 1;
+   error:
+@@ -577,6 +580,9 @@ htx_set_comp_reshdr(struct comp_state *st, struct stream *s, struct http_msg *ms
+               }
+       }
++      if (!http_add_header(htx, ist("Vary"), ist("Accept-Encoding")))
++              goto error;
++
+       return 1;
+   error:
diff --git a/net/haproxy/patches/003-DOC-contrib-modsecurity-Typos-and-fix-the-reject-example.patch b/net/haproxy/patches/003-DOC-contrib-modsecurity-Typos-and-fix-the-reject-example.patch
deleted file mode 100644 (file)
index 514c4c5..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-commit dfc3718f0a302ea3deb5f1a325d35fce0e4cfa48
-Author: Yann Cézard <ycezard@viareport.com>
-Date:   Thu Apr 25 14:48:38 2019 +0200
-
-    DOC: contrib/modsecurity: Typos and fix the reject example
-    
-    Thanks to https://www.mail-archive.com/haproxy@formilux.org/msg30056.html
-    
-    This patch may be backported to 1.9 and 1.8.
-    
-    (cherry picked from commit 494ddbff478d880e48de490f2689607addac70bc)
-    Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
-    (cherry picked from commit 850896603086877641272d6e4075e66bd91f2e50)
-    Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
-
-diff --git a/contrib/modsecurity/README b/contrib/modsecurity/README
-index e6cb305e..8031389d 100644
---- a/contrib/modsecurity/README
-+++ b/contrib/modsecurity/README
-@@ -88,15 +88,15 @@ HAProxy configuration. For example:
-       balance roundrobin
-       timeout connect 5s
-       timeout server  3m
--      server iprep1 127.0.0.1:12345
-+      server modsec1 127.0.0.1:12345
- The modsecurity action is returned in a variable called txn.modsec.code. It
- contains the HTTP returned code. If the variable contains 0, the request is
- clean.
--   tcp-request content reject if { var(txn.modsec.code) -m int gt 0 }
-+   http-request deny if { var(txn.modsec.code) -m int gt 0 }
--With this rule, all the request not clean are reected.
-+With this rule, all the request not clean are rejected.
-   Known bugs, limitations and TODO list
diff --git a/net/haproxy/patches/004-BUG-MEDIUM-contrib-modsecurity-If-host-header-is-NULL-dont-try-to-strdup-it.patch b/net/haproxy/patches/004-BUG-MEDIUM-contrib-modsecurity-If-host-header-is-NULL-dont-try-to-strdup-it.patch
deleted file mode 100644 (file)
index af49cc2..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-commit 95cf225d099dcb49eefcf4f5b648be604414ae0c
-Author: Yann Cézard <ycezard@viareport.com>
-Date:   Thu Apr 25 14:30:23 2019 +0200
-
-    BUG/MEDIUM: contrib/modsecurity: If host header is NULL, don't try to strdup it
-    
-    I discovered this bug when running OWASP regression tests against HAProxy +
-    modsecurity-spoa (it's a POC to evaluate how it is working).  I found out that
-    modsecurity spoa will crash when the request doesn't have any Host header.
-    
-    See the pull request #86 on github for details.
-    
-    This patch must be backported to 1.9 and 1.8.
-    
-    (cherry picked from commit bf60f6b8033deddc86de5357d6099c7593fe44cc)
-    Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
-    (cherry picked from commit d988e3dddcbe1f48f3b24d1bb529fc9ecefde180)
-    Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
-
-diff --git a/contrib/modsecurity/modsec_wrapper.c b/contrib/modsecurity/modsec_wrapper.c
-index 271ec15d..2f3987b4 100644
---- a/contrib/modsecurity/modsec_wrapper.c
-+++ b/contrib/modsecurity/modsec_wrapper.c
-@@ -325,7 +325,11 @@ int modsecurity_process(struct worker *worker, struct modsecurity_parameters *pa
-       req->content_type = apr_table_get(req->headers_in, "Content-Type");
-       req->content_encoding = apr_table_get(req->headers_in, "Content-Encoding");
-       req->hostname = apr_table_get(req->headers_in, "Host");
--      req->parsed_uri.hostname = chunk_strdup(req, req->hostname, strlen(req->hostname));
-+      if (req->hostname != NULL) {
-+              req->parsed_uri.hostname = chunk_strdup(req, req->hostname, strlen(req->hostname));
-+      } else {
-+              req->parsed_uri.hostname = NULL;
-+      }
-       lang = apr_table_get(req->headers_in, "Content-Languages");
-       if (lang != NULL) {
diff --git a/net/haproxy/patches/004-MINOR-htx-Add-the-function-htx_change_blk_value_len.patch b/net/haproxy/patches/004-MINOR-htx-Add-the-function-htx_change_blk_value_len.patch
new file mode 100644 (file)
index 0000000..7c308f7
--- /dev/null
@@ -0,0 +1,66 @@
+commit 8d09dc21dc913d1540d07d1019a51c430317eae1
+Author: Christopher Faulet <cfaulet@haproxy.com>
+Date:   Tue Jun 18 09:37:00 2019 +0200
+
+    MINOR: htx: Add the function htx_change_blk_value_len()
+    
+    As its name suggest, this function change the value length of a block. But it
+    also update the HTX message accordingly. It simplifies the HTX API. The function
+    htx_set_blk_value_len() is still available and must be used with caution because
+    this one does not update the HTX message. It just updates the HTX block. It
+    should be considered as an internal function. When possible,
+    htx_change_blk_value_len() should be used instead.
+    
+    This function is used to fix a bug affecting the 2.0. So, this patch must be
+    backported to 2.0.
+    
+    (cherry picked from commit bb0efcdd293de33607a6eba075971b49857375e2)
+    Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
+
+diff --git a/include/common/htx.h b/include/common/htx.h
+index 9631c618..7d15365a 100644
+--- a/include/common/htx.h
++++ b/include/common/htx.h
+@@ -470,7 +470,41 @@ static inline struct htx_blk *htx_get_next_blk(const struct htx *htx,
+ }
+ /* Changes the size of the value. It is the caller responsibility to change the
+- * value itself, make sure there is enough space and update allocated value.
++ * value itself, make sure there is enough space and update allocated
++ * value. This function updates the HTX message accordingly.
++ */
++static inline void htx_change_blk_value_len(struct htx *htx, struct htx_blk *blk, uint32_t newlen)
++{
++      enum htx_blk_type type = htx_get_blk_type(blk);
++      uint32_t oldlen, sz;
++      int32_t delta;
++
++      sz = htx_get_blksz(blk);
++      switch (type) {
++              case HTX_BLK_HDR:
++              case HTX_BLK_TLR:
++                      oldlen = (blk->info >> 8) & 0xfffff;
++                      blk->info = (type << 28) + (newlen << 8) + (blk->info & 0xff);
++                      break;
++              default:
++                      oldlen = blk->info & 0xfffffff;
++                      blk->info = (type << 28) + newlen;
++                      break;
++      }
++
++      /* Update HTTP message */
++      delta = (newlen - oldlen);
++      htx->data += delta;
++      if (blk->addr+sz == htx->tail_addr)
++              htx->tail_addr += delta;
++      else if (blk->addr+sz == htx->head_addr)
++              htx->head_addr += delta;
++}
++
++/* Changes the size of the value. It is the caller responsibility to change the
++ * value itself, make sure there is enough space and update allocated
++ * value. Unlike the function htx_change_blk_value_len(), this one does not
++ * update the HTX message. So it should be used with caution.
+  */
+ static inline void htx_set_blk_value_len(struct htx_blk *blk, uint32_t vlen)
+ {
diff --git a/net/haproxy/patches/005-BUG-MEDIUM-htx-Fully-update-HTX-message-when-the-block-value-is-changed.patch b/net/haproxy/patches/005-BUG-MEDIUM-htx-Fully-update-HTX-message-when-the-block-value-is-changed.patch
new file mode 100644 (file)
index 0000000..5a9fda4
--- /dev/null
@@ -0,0 +1,133 @@
+commit 41dc8432f87622145390dc1b1467a5ee14ba184c
+Author: Christopher Faulet <cfaulet@haproxy.com>
+Date:   Tue Jun 18 09:49:16 2019 +0200
+
+    BUG/MEDIUM: htx: Fully update HTX message when the block value is changed
+    
+    Everywhere the value length of a block is changed, calling the function
+    htx_set_blk_value_len(), the HTX message must be updated. But at many places,
+    because of the recent changes in the HTX structure, this update was only
+    partially done. tail_addr and head_addr values were not systematically updated.
+    
+    In fact, the function htx_set_blk_value_len() was designed as an internal
+    function to the HTX API. And we used it from outside by convenience. But it is
+    really painfull and error prone to let the caller update the HTX message. So
+    now, we use the function htx_change_blk_value_len() wherever is possible. It
+    changes the value length of a block and updates the HTX message accordingly.
+    
+    This patch must be backported to 2.0.
+    
+    (cherry picked from commit 3e2638ee04407a1d9e9376f0c518f67fca7deaa4)
+    Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
+
+diff --git a/src/h2.c b/src/h2.c
+index 32c1ef16..990d602b 100644
+--- a/src/h2.c
++++ b/src/h2.c
+@@ -736,8 +736,7 @@ int h2_make_htx_request(struct http_hdr *list, struct htx *htx, unsigned int *ms
+                       if (tl > fs)
+                               goto fail;
+-                      htx_set_blk_value_len(blk, tl);
+-                      htx->data += vl+2;
++                      htx_change_blk_value_len(htx, blk, tl);
+                       *(char *)(htx_get_blk_ptr(htx, blk) + bs + 0) = ';';
+                       *(char *)(htx_get_blk_ptr(htx, blk) + bs + 1) = ' ';
+                       memcpy(htx_get_blk_ptr(htx, blk) + bs + 2, list[ck].v.ptr, vl);
+diff --git a/src/http_htx.c b/src/http_htx.c
+index 7322b337..bc26e5ba 100644
+--- a/src/http_htx.c
++++ b/src/http_htx.c
+@@ -461,10 +461,7 @@ int http_remove_header(struct htx *htx, struct http_hdr_ctx *ctx)
+       }
+       /* Update the block content and its len */
+       memmove(start, start+len, v.len-len);
+-      htx_set_blk_value_len(blk, v.len-len);
+-
+-      /* Update HTX msg */
+-      htx->data -= len;
++      htx_change_blk_value_len(htx, blk, v.len-len);
+       /* Finally update the ctx */
+       ctx->value.ptr = start;
+diff --git a/src/htx.c b/src/htx.c
+index bfd136f4..81492598 100644
+--- a/src/htx.c
++++ b/src/htx.c
+@@ -406,15 +406,8 @@ void htx_truncate(struct htx *htx, uint32_t offset)
+                       offset -= sz;
+                       continue;
+               }
+-              if (type == HTX_BLK_DATA) {
+-                      htx_set_blk_value_len(blk, offset);
+-                      htx->data -= (sz - offset);
+-
+-                      if (blk->addr+sz == htx->tail_addr)
+-                              htx->tail_addr -= offset;
+-                      else if (blk->addr+sz == htx->head_addr)
+-                              htx->head_addr -= offset;
+-              }
++              if (type == HTX_BLK_DATA)
++                      htx_change_blk_value_len(htx, blk, offset);
+               offset = 0;
+       }
+       while (blk)
+@@ -522,14 +515,7 @@ struct htx_blk *htx_add_data_atonce(struct htx *htx, struct ist data)
+       /* Append data and update the block itself */
+       ptr = htx_get_blk_ptr(htx, tailblk);
+       memcpy(ptr+sz, data.ptr, len);
+-      htx_set_blk_value_len(tailblk, sz+len);
+-
+-      /* Update HTTP message */
+-      htx->data += len;
+-      if (tailblk->addr+sz == htx->tail_addr)
+-              htx->tail_addr += len;
+-      else if (tailblk->addr+sz == htx->head_addr)
+-              htx->head_addr += len;
++      htx_change_blk_value_len(htx, tailblk, sz+len);
+       if (data.len == len) {
+               blk = tailblk;
+@@ -988,14 +974,7 @@ size_t htx_add_data(struct htx *htx, const struct ist data)
+       /* Append data and update the block itself */
+       ptr = htx_get_blk_ptr(htx, tailblk);
+       memcpy(ptr + sz, data.ptr, len);
+-      htx_set_blk_value_len(tailblk, sz + len);
+-
+-      /* Update HTTP message */
+-      htx->data += len;
+-      if (tailblk->addr+sz == htx->tail_addr)
+-              htx->tail_addr += len;
+-      else if (tailblk->addr+sz == htx->head_addr)
+-              htx->head_addr += len;
++      htx_change_blk_value_len(htx, tailblk, sz+len);
+       BUG_ON((int32_t)htx->tail_addr < 0);
+       BUG_ON((int32_t)htx->head_addr < 0);
+diff --git a/src/proto_htx.c b/src/proto_htx.c
+index 7f501366..d821e38c 100644
+--- a/src/proto_htx.c
++++ b/src/proto_htx.c
+@@ -4314,10 +4314,8 @@ static void htx_manage_client_side_cookies(struct stream *s, struct channel *req
+                       hdr_end = (preserve_hdr ? del_from : hdr_beg);
+               }
+               if ((hdr_end - hdr_beg) != ctx.value.len) {
+-                      if (hdr_beg != hdr_end) {
+-                              htx_set_blk_value_len(ctx.blk, hdr_end - hdr_beg);
+-                              htx->data -= ctx.value.len - (hdr_end - hdr_beg);
+-                      }
++                      if (hdr_beg != hdr_end)
++                              htx_change_blk_value_len(htx, ctx.blk, hdr_end - hdr_beg);
+                       else
+                               http_remove_header(htx, &ctx);
+               }
+@@ -4495,8 +4493,7 @@ static void htx_manage_server_side_cookies(struct stream *s, struct channel *res
+                               next         += stripped_before;
+                               hdr_end      += stripped_before;
+-                              htx_set_blk_value_len(ctx.blk, hdr_end - hdr_beg);
+-                              htx->data -= ctx.value.len - (hdr_end - hdr_beg);
++                              htx_change_blk_value_len(htx, ctx.blk, hdr_end - hdr_beg);
+                               ctx.value.len = hdr_end - hdr_beg;
+                       }
diff --git a/net/haproxy/patches/005-MINOR-examples-Use-right-locale-for-the-last-changelog-date-in-haproxy-spec.patch b/net/haproxy/patches/005-MINOR-examples-Use-right-locale-for-the-last-changelog-date-in-haproxy-spec.patch
deleted file mode 100644 (file)
index 310dc0f..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-commit 86860896dc1841eb59cb95832d76a8093e8dc8c5
-Author: Christopher Faulet <cfaulet@haproxy.com>
-Date:   Tue Apr 30 10:55:38 2019 +0200
-
-    MINOR: examples: Use right locale for the last changelog date in haproxy.spec
-    
-    The last changelog entry was stamped with the wrong locale.
-    
-    No need to backport, it is specific to 1.8
-
-diff --git a/examples/haproxy.spec b/examples/haproxy.spec
-index f3e0c7e0..fe5215d7 100644
---- a/examples/haproxy.spec
-+++ b/examples/haproxy.spec
-@@ -74,7 +74,7 @@ fi
- %attr(0755,root,root) %config %{_sysconfdir}/rc.d/init.d/%{name}
- %changelog
--* jeu. avril 25 2019 Christopher Faulet <cfaulet@haproxy.com>
-+* Thu Apr 25 2019 Christopher Faulet <cfaulet@haproxy.com>
- - updated to 1.8.20
- * Mon Feb 11 2019 Willy Tarreau <w@1wt.eu>
diff --git a/net/haproxy/patches/006-BUG-MAJOR-map-acl-real-fix-segfault-during-show-map-acl-on-CLI.patch b/net/haproxy/patches/006-BUG-MAJOR-map-acl-real-fix-segfault-during-show-map-acl-on-CLI.patch
deleted file mode 100644 (file)
index e961294..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-commit 83af1f6b65806982640679823228976deebf5202
-Author: Willy Tarreau <w@1wt.eu>
-Date:   Tue Apr 30 11:43:43 2019 +0200
-
-    BUG/MAJOR: map/acl: real fix segfault during show map/acl on CLI
-    
-    A previous commit 8d85aa44d ("BUG/MAJOR: map: fix segfault during
-    'show map/acl' on cli.") was provided to address a concurrency issue
-    between "show acl" and "clear acl" on the CLI. Sadly the code placed
-    there was copy-pasted without changing the element type (which was
-    struct stream in the original code) and not tested since the crash
-    is still present.
-    
-    The reproducer is simple : load a large ACL file (e.g. geolocation
-    addresses), issue "show acl #0" in loops in one window and issue a
-    "clear acl #0" in the other one, haproxy crashes.
-    
-    This fix was also tested with threads enabled and looks good since
-    the locking seems to work correctly in these areas though. It will
-    have to be backported as far as 1.6 since the commit above went
-    that far as well...
-    
-    (cherry picked from commit 49ee3b2f9a9e5d0b8d394938df527aa645ce72b4)
-    Signed-off-by: Willy Tarreau <w@1wt.eu>
-    (cherry picked from commit ac4be10f62ef72962d9cf0e6f2619e1e1c370d62)
-    Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
-
-diff --git a/src/pattern.c b/src/pattern.c
-index 7eea9d96..21639569 100644
---- a/src/pattern.c
-+++ b/src/pattern.c
-@@ -1651,7 +1651,7 @@ int pat_ref_delete_by_id(struct pat_ref *ref, struct pat_ref_elt *refelt)
-                               LIST_DEL(&bref->users);
-                               LIST_INIT(&bref->users);
-                               if (elt->list.n != &ref->head)
--                                      LIST_ADDQ(&LIST_ELEM(elt->list.n, struct stream *, list)->back_refs, &bref->users);
-+                                      LIST_ADDQ(&LIST_ELEM(elt->list.n, typeof(elt), list)->back_refs, &bref->users);
-                               bref->ref = elt->list.n;
-                       }
-                       list_for_each_entry(expr, &ref->pat, list)
-@@ -1691,7 +1691,7 @@ int pat_ref_delete(struct pat_ref *ref, const char *key)
-                               LIST_DEL(&bref->users);
-                               LIST_INIT(&bref->users);
-                               if (elt->list.n != &ref->head)
--                                      LIST_ADDQ(&LIST_ELEM(elt->list.n, struct stream *, list)->back_refs, &bref->users);
-+                                      LIST_ADDQ(&LIST_ELEM(elt->list.n, typeof(elt), list)->back_refs, &bref->users);
-                               bref->ref = elt->list.n;
-                       }
-                       list_for_each_entry(expr, &ref->pat, list)
-@@ -2086,7 +2086,7 @@ void pat_ref_reload(struct pat_ref *ref, struct pat_ref *replace)
-                       LIST_DEL(&bref->users);
-                       LIST_INIT(&bref->users);
-                       if (elt->list.n != &ref->head)
--                              LIST_ADDQ(&LIST_ELEM(elt->list.n, struct stream *, list)->back_refs, &bref->users);
-+                              LIST_ADDQ(&LIST_ELEM(elt->list.n, typeof(elt), list)->back_refs, &bref->users);
-                       bref->ref = elt->list.n;
-               }
-               LIST_DEL(&elt->list);
-@@ -2175,7 +2175,7 @@ void pat_ref_prune(struct pat_ref *ref)
-                       LIST_DEL(&bref->users);
-                       LIST_INIT(&bref->users);
-                       if (elt->list.n != &ref->head)
--                              LIST_ADDQ(&LIST_ELEM(elt->list.n, struct stream *, list)->back_refs, &bref->users);
-+                              LIST_ADDQ(&LIST_ELEM(elt->list.n, typeof(elt), list)->back_refs, &bref->users);
-                       bref->ref = elt->list.n;
-               }
-               LIST_DEL(&elt->list);
diff --git a/net/haproxy/patches/006-BUG-MEDIUM-mux-h2-Reset-padlen-when-several-frames-are-demux.patch b/net/haproxy/patches/006-BUG-MEDIUM-mux-h2-Reset-padlen-when-several-frames-are-demux.patch
new file mode 100644 (file)
index 0000000..3a18eee
--- /dev/null
@@ -0,0 +1,27 @@
+commit 3d574a587dc3704e93bcd29b16d54d96069667b4
+Author: Christopher Faulet <cfaulet@haproxy.com>
+Date:   Tue Jun 18 12:22:38 2019 +0200
+
+    BUG/MEDIUM: mux-h2: Reset padlen when several frames are demux
+    
+    In the function h2_process_demux(), if several frames are parsed, the padding
+    length must be reset between each frame. Otherwise we may wrongly think a frame
+    has a padding block because the previous one was padded.
+    
+    This patch must be backported to 2.0 and 1.9.
+    
+    (cherry picked from commit dd2a5620d594523cd515a629e105a9a2b64345bb)
+    Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
+
+diff --git a/src/mux_h2.c b/src/mux_h2.c
+index d02168df..c06d5d68 100644
+--- a/src/mux_h2.c
++++ b/src/mux_h2.c
+@@ -2316,6 +2316,7 @@ static void h2_process_demux(struct h2c *h2c)
+                               break;
+                       }
++                      padlen = 0;
+                       if (h2_ft_bit(hdr.ft) & H2_FT_PADDED_MASK && hdr.ff & H2_F_PADDED) {
+                               /* If the frame is padded (HEADERS, PUSH_PROMISE or DATA),
+                                * we read the pad length and drop it from the remaining
diff --git a/net/haproxy/patches/007-BUG-MEDIUM-listener-Fix-how-unlimited-number-of-consecutive-accepts-is-handled.patch b/net/haproxy/patches/007-BUG-MEDIUM-listener-Fix-how-unlimited-number-of-consecutive-accepts-is-handled.patch
deleted file mode 100644 (file)
index e54c530..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-commit 7bd7a8d2b8889f604b807c21190d2e70328d6674
-Author: Christopher Faulet <cfaulet@haproxy.com>
-Date:   Tue Apr 30 12:17:13 2019 +0200
-
-    BUG/MEDIUM: listener: Fix how unlimited number of consecutive accepts is handled
-    
-    There is a bug when global.tune.maxaccept is set to -1 (no limit). It is pretty
-    visible with one process (nbproc sets to 1). The functions listener_accept() and
-    accept_queue_process() don't expect to handle negative maxaccept values. So
-    instead of accepting incoming connections without any limit, none are never
-    accepted and HAProxy loop infinitly in the scheduler.
-    
-    When there are 2 or more processes, the bug is a bit more subtile. The limit for
-    a listener is set to 1. So only one connection is accepted at a time by a given
-    listener. This happens because the listener's maxaccept value is an unsigned
-    integer. In check_config_validity(), it is first set to UINT_MAX (-1 casted in
-    an unsigned integer), and then some calculations on it leads to an integer
-    overflow.
-    
-    To fix the bug, the listener's maxaccept value is now a signed integer. So, if a
-    negative value is set for global.tune.maxaccept, we keep it untouched for the
-    listener and no calculation is made on it. Then, in the listener code, this
-    signed value is casted to a unsigned one. It simplifies all tests instead of
-    dealing with negative values. So, it limits the number of connections accepted
-    at a time to UINT_MAX at most. But, honestly, it not an issue.
-    
-    This patch must be backported to 1.9 and 1.8.
-    
-    (cherry picked from commit 102854cbbaa4d22466dddec9035d411db244082f)
-    Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
-    (cherry picked from commit bca4fb2d9d7f2966d9f8270fa1796fdc0dfc866d)
-    Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
-
-diff --git a/include/types/listener.h b/include/types/listener.h
-index ea2eadb5..16ef6d7a 100644
---- a/include/types/listener.h
-+++ b/include/types/listener.h
-@@ -196,7 +196,7 @@ struct listener {
-       int nbconn;                     /* current number of connections on this listener */
-       int maxconn;                    /* maximum connections allowed on this listener */
-       unsigned int backlog;           /* if set, listen backlog */
--      unsigned int maxaccept;         /* if set, max number of connections accepted at once */
-+      int maxaccept;         /* if set, max number of connections accepted at once (-1 when disabled) */
-       struct list proto_list;         /* list in the protocol header */
-       int (*accept)(struct listener *l, int fd, struct sockaddr_storage *addr); /* upper layer's accept() */
-       enum obj_type *default_target;  /* default target to use for accepted sessions or NULL */
-diff --git a/src/listener.c b/src/listener.c
-index 821c931a..74990c45 100644
---- a/src/listener.c
-+++ b/src/listener.c
-@@ -406,7 +406,7 @@ void listener_accept(int fd)
- {
-       struct listener *l = fdtab[fd].owner;
-       struct proxy *p;
--      int max_accept;
-+      unsigned int max_accept;
-       int next_conn = 0;
-       int next_feconn = 0;
-       int next_actconn = 0;
-@@ -420,6 +420,10 @@ void listener_accept(int fd)
-       if (!l)
-               return;
-       p = l->bind_conf->frontend;
-+
-+      /* if l->maxaccept is -1, then max_accept is UINT_MAX. It is not really
-+       * illimited, but it is probably enough.
-+       */
-       max_accept = l->maxaccept ? l->maxaccept : 1;
-       if (!(l->options & LI_O_UNLIMITED) && global.sps_lim) {
-@@ -480,7 +484,7 @@ void listener_accept(int fd)
-        * worst case. If we fail due to system limits or temporary resource
-        * shortage, we try again 100ms later in the worst case.
-        */
--      for (; max_accept-- > 0; next_conn = next_feconn = next_actconn = 0) {
-+      for (; max_accept; next_conn = next_feconn = next_actconn = 0, max_accept--) {
-               struct sockaddr_storage addr;
-               socklen_t laddr = sizeof(addr);
-               unsigned int count;
diff --git a/net/haproxy/patches/007-BUG-MEDIUM-mux-h2-Remove-the-padding-length-when-a-DATA-frame-size-is-checked.patch b/net/haproxy/patches/007-BUG-MEDIUM-mux-h2-Remove-the-padding-length-when-a-DATA-frame-size-is-checked.patch
new file mode 100644 (file)
index 0000000..d23f66f
--- /dev/null
@@ -0,0 +1,30 @@
+commit 4fb65f421b4d650711e5d8b9dbcbf4bf589d26cc
+Author: Christopher Faulet <cfaulet@haproxy.com>
+Date:   Wed Jun 19 09:25:58 2019 +0200
+
+    BUG/MEDIUM: mux-h2: Remove the padding length when a DATA frame size is checked
+    
+    When a DATA frame is processed for a message with a content-length, we first
+    take care to not have a frame size that exceeds the remaining to
+    read. Otherwise, an error is triggered. But we must remove the padding length
+    from the frame size because the padding is not included in the announced
+    content-length.
+    
+    This patch must be backported to 2.0 and 1.9.
+    
+    (cherry picked from commit 4f09ec812adbd9336cddc054660a7fb5cd54b459)
+    Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
+
+diff --git a/src/mux_h2.c b/src/mux_h2.c
+index c06d5d68..5bb85181 100644
+--- a/src/mux_h2.c
++++ b/src/mux_h2.c
+@@ -2177,7 +2177,7 @@ static int h2c_frt_handle_data(struct h2c *h2c, struct h2s *h2s)
+               goto strm_err;
+       }
+-      if ((h2s->flags & H2_SF_DATA_CLEN) && h2c->dfl > h2s->body_len) {
++      if ((h2s->flags & H2_SF_DATA_CLEN) && (h2c->dfl - h2c->dpl) > h2s->body_len) {
+               /* RFC7540#8.1.2 */
+               error = H2_ERR_PROTOCOL_ERROR;
+               goto strm_err;
diff --git a/net/haproxy/patches/008-BUG-MEDIUM-lb_fwlc-Dont-test-the-servers-lb_tree-from-outside-the-lock.patch b/net/haproxy/patches/008-BUG-MEDIUM-lb_fwlc-Dont-test-the-servers-lb_tree-from-outside-the-lock.patch
new file mode 100644 (file)
index 0000000..129c0b7
--- /dev/null
@@ -0,0 +1,39 @@
+commit 3f0b1de623d09f8668db34c1be696f7245de7d50
+Author: Christopher Faulet <cfaulet@haproxy.com>
+Date:   Wed Jun 19 10:50:38 2019 +0200
+
+    BUG/MEDIUM: lb_fwlc: Don't test the server's lb_tree from outside the lock
+    
+    In the function fwlc_srv_reposition(), the server's lb_tree is tested from
+    outside the lock. So it is possible to remove it after the test and then call
+    eb32_insert() in fwlc_queue_srv() with a NULL root pointer, which is
+    invalid. Moving the test in the scope of the lock fixes the bug.
+    
+    This issue was reported on Github, issue #126.
+    
+    This patch must be backported to 2.0, 1.9 and 1.8.
+    
+    (cherry picked from commit 1ae2a8878170ded922f2c4d32b6704af7689bbfd)
+    Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
+
+diff --git a/src/lb_fwlc.c b/src/lb_fwlc.c
+index 174dc67e..5fa81739 100644
+--- a/src/lb_fwlc.c
++++ b/src/lb_fwlc.c
+@@ -66,12 +66,11 @@ static inline void fwlc_queue_srv(struct server *s)
+  */
+ static void fwlc_srv_reposition(struct server *s)
+ {
+-      if (!s->lb_tree)
+-              return;
+-
+       HA_SPIN_LOCK(LBPRM_LOCK, &s->proxy->lbprm.lock);
+-      fwlc_dequeue_srv(s);
+-      fwlc_queue_srv(s);
++      if (s->lb_tree) {
++              fwlc_dequeue_srv(s);
++              fwlc_queue_srv(s);
++      }
+       HA_SPIN_UNLOCK(LBPRM_LOCK, &s->proxy->lbprm.lock);
+ }
diff --git a/net/haproxy/patches/008-MINOR-config-Test-validity-of-tune-maxaccept-during-the-config-parsing.patch b/net/haproxy/patches/008-MINOR-config-Test-validity-of-tune-maxaccept-during-the-config-parsing.patch
deleted file mode 100644 (file)
index 5c5d889..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-commit 6e580b6e744011e87c337ebe2c082acfd5ca835a
-Author: Christopher Faulet <cfaulet@haproxy.com>
-Date:   Tue Apr 30 14:03:56 2019 +0200
-
-    MINOR: config: Test validity of tune.maxaccept during the config parsing
-    
-    Only -1 and positive integers from 0 to INT_MAX are accepted. An error is
-    triggered during the config parsing for any other values.
-    
-    This patch may be backported to all supported versions.
-    
-    (cherry picked from commit 6b02ab87348090efec73b1dd24f414239669f279)
-    Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
-    (cherry picked from commit 2bbc40f8bc9a52ba0d03b25270ac0129cca29bba)
-    Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
-
-diff --git a/src/cfgparse.c b/src/cfgparse.c
-index c178538b..8e325416 100644
---- a/src/cfgparse.c
-+++ b/src/cfgparse.c
-@@ -789,6 +789,8 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
-               global.tune.maxpollevents = atol(args[1]);
-       }
-       else if (!strcmp(args[0], "tune.maxaccept")) {
-+              long max;
-+
-               if (alertif_too_many_args(1, file, linenum, args, &err_code))
-                       goto out;
-               if (global.tune.maxaccept != 0) {
-@@ -801,7 +803,13 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
-                       err_code |= ERR_ALERT | ERR_FATAL;
-                       goto out;
-               }
--              global.tune.maxaccept = atol(args[1]);
-+              max = atol(args[1]);
-+              if (/*max < -1 || */max > INT_MAX) {
-+                      ha_alert("parsing [%s:%d] : '%s' expects -1 or an integer from 0 to INT_MAX.\n", file, linenum, args[0]);
-+                      err_code |= ERR_ALERT | ERR_FATAL;
-+                      goto out;
-+              }
-+              global.tune.maxaccept = max;
-       }
-       else if (!strcmp(args[0], "tune.chksize")) {
-               if (alertif_too_many_args(1, file, linenum, args, &err_code))
diff --git a/net/haproxy/patches/009-CLEANUP-config-Dont-alter-listener--maxaccept-when-nbproc-is-set-to-1.patch b/net/haproxy/patches/009-CLEANUP-config-Dont-alter-listener--maxaccept-when-nbproc-is-set-to-1.patch
deleted file mode 100644 (file)
index 4bcae44..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-commit c6e03c1495fa51f9a98ed0bbe3230313c7c7201c
-Author: Christopher Faulet <cfaulet@haproxy.com>
-Date:   Tue Apr 30 14:08:41 2019 +0200
-
-    CLEANUP: config: Don't alter listener->maxaccept when nbproc is set to 1
-    
-    This patch only removes a useless calculation on listener->maxaccept when nbproc
-    is set to 1. Indeed, the following formula has no effet in such case:
-    
-      listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
-    
-    This patch may be backported as far as 1.5.
-    
-    (cherry picked from commit 02f3cf19ed803d20aff9294ce7cb732489951ff5)
-    Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
-    (cherry picked from commit 14203e3cf9404e57de5e274b453f0fe4f2174924)
-    Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
-
-diff --git a/src/cfgparse.c b/src/cfgparse.c
-index 8e325416..3f6ea352 100644
---- a/src/cfgparse.c
-+++ b/src/cfgparse.c
-@@ -9018,9 +9018,8 @@ out_uri_auth_compat:
-                        * is bound to. Rememeber that maxaccept = -1 must be kept as it is
-                        * used to disable the limit.
-                        */
--                      if (listener->maxaccept > 0) {
--                              if (nbproc > 1)
--                                      listener->maxaccept = (listener->maxaccept + 1) / 2;
-+                      if (listener->maxaccept > 0 && nbproc > 1) {
-+                              listener->maxaccept = (listener->maxaccept + 1) / 2;
-                               listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
-                       }
diff --git a/net/haproxy/patches/010-MINOR-threads-Implement-HA_ATOMIC_LOAD.patch b/net/haproxy/patches/010-MINOR-threads-Implement-HA_ATOMIC_LOAD.patch
deleted file mode 100644 (file)
index 30e8cd4..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-commit f95cf6ad70565ee2322cf23bc519b7bb0b3831b2
-Author: Olivier Houchard <ohouchard@haproxy.com>
-Date:   Tue Apr 30 13:38:02 2019 +0200
-
-    MINOR: threads: Implement HA_ATOMIC_LOAD().
-    
-    The same way we have HA_ATOMIC_STORE(), implement HA_ATOMIC_LOAD().
-    
-    This should be backported to 1.8 and 1.9, as we need it for a bug fix
-    in port ranges.
-    
-    (cherry picked from commit 9ce62b5498b27fbf4217d9c25779d5b2ceca23f2)
-    Signed-off-by: Olivier Houchard <cognet@ci0.org>
-    (cherry picked from commit 358c979611370fa2bc3b8e47ed50a325cf9126cf)
-    Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
-
-diff --git a/include/common/hathreads.h b/include/common/hathreads.h
-index 8134839a..11d7cab6 100644
---- a/include/common/hathreads.h
-+++ b/include/common/hathreads.h
-@@ -62,6 +62,7 @@ enum { tid = 0 };
-               *(val) = new;                                           \
-               __old_xchg;                                             \
-       })
-+#define HA_ATOMIC_LOAD(val)          *(val)
- #define HA_ATOMIC_STORE(val, new)    ({*(val) = new;})
- #define HA_ATOMIC_UPDATE_MAX(val, new)                                        \
-       ({                                                              \
-@@ -203,6 +204,16 @@ static inline unsigned long thread_isolated()
-               } while (!__sync_bool_compare_and_swap(__val_xchg, __old_xchg, __new_xchg)); \
-               __old_xchg;                                             \
-       })
-+
-+#define HA_ATOMIC_LOAD(val)                                             \
-+        ({                                                              \
-+              typeof(*(val)) ret;                                     \
-+              __sync_synchronize();                                   \
-+              ret = *(volatile typeof(val))val;                       \
-+              __sync_synchronize();                                   \
-+              ret;                                                    \
-+      })
-+
- #define HA_ATOMIC_STORE(val, new)                                     \
-       ({                                                              \
-               typeof((val)) __val_store = (val);                      \
-@@ -221,6 +232,8 @@ static inline unsigned long thread_isolated()
- #define HA_ATOMIC_OR(val, flags)     __atomic_or_fetch(val,  flags, __ATOMIC_SEQ_CST)
- #define HA_ATOMIC_XCHG(val, new)     __atomic_exchange_n(val, new, __ATOMIC_SEQ_CST)
- #define HA_ATOMIC_STORE(val, new)    __atomic_store_n(val, new, __ATOMIC_SEQ_CST)
-+#define HA_ATOMIC_LOAD(val)          __atomic_load_n(val, __ATOMIC_SEQ_CST)
-+
- #endif
- #define HA_ATOMIC_UPDATE_MAX(val, new)                                        \
diff --git a/net/haproxy/patches/011-BUG-MEDIUM-port_range-Make-the-ring-buffer-lock-free.patch b/net/haproxy/patches/011-BUG-MEDIUM-port_range-Make-the-ring-buffer-lock-free.patch
deleted file mode 100644 (file)
index 68332fd..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-commit 31470e2ba2aabb4c6340fbc15cb5486ceb8c69c8
-Author: Olivier Houchard <ohouchard@haproxy.com>
-Date:   Mon Apr 29 18:52:06 2019 +0200
-
-    BUG/MEDIUM: port_range: Make the ring buffer lock-free.
-    
-    Port range uses a ring buffer, and unfortunately, when making haproxy
-    multithreaded, it's been overlooked, and the ring buffer is not thread-safe.
-    When specifying a source range, 2 or more threads could pick the same
-    port, and of course only one of them could use the port, the others would
-    always fail the connection.
-    To fix this, make it a lock-free ring buffer. This is easier than usual
-    because we know the ring buffer can never be full.
-    
-    This should be backported to 1.8 and 1.9.
-    
-    (cherry picked from commit 07425de71777b688e77a9c70a7088c13e66e41e9)
-    Signed-off-by: Olivier Houchard <cognet@ci0.org>
-    (cherry picked from commit bffb51147a4a5939e344b3c838628f9a944febef)
-    Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
-
-diff --git a/include/proto/port_range.h b/include/proto/port_range.h
-index 8c63faca..f7e3f1d5 100644
---- a/include/proto/port_range.h
-+++ b/include/proto/port_range.h
-@@ -24,18 +24,22 @@
- #include <types/port_range.h>
-+#define GET_NEXT_OFF(range, off) ((off) == (range)->size - 1 ? 0 : (off) + 1)
-+
- /* return an available port from range <range>, or zero if none is left */
- static inline int port_range_alloc_port(struct port_range *range)
- {
-       int ret;
-+      int get;
-+      int put;
--      if (!range->avail)
--              return 0;
--      ret = range->ports[range->get];
--      range->get++;
--      if (range->get >= range->size)
--              range->get = 0;
--      range->avail--;
-+      get = HA_ATOMIC_LOAD(&range->get);
-+      do {
-+              put = HA_ATOMIC_LOAD(&range->put_t);
-+              if (unlikely(put == get))
-+                      return 0;
-+              ret = range->ports[get];
-+      } while (!(HA_ATOMIC_CAS(&range->get, &get, GET_NEXT_OFF(range, get))));
-       return ret;
- }
-@@ -45,14 +49,28 @@ static inline int port_range_alloc_port(struct port_range *range)
-  */
- static inline void port_range_release_port(struct port_range *range, int port)
- {
-+      int put;
-+
-       if (!port || !range)
-               return;
--      range->ports[range->put] = port;
--      range->avail++;
--      range->put++;
--      if (range->put >= range->size)
--              range->put = 0;
-+      put = range->put_h;
-+      /* put_h is reserved for producers, so that they can each get a
-+       * free slot, put_t is what is used by consumers to know if there's
-+       * elements available or not
-+       */
-+      /* First reserve or slot, we know the ring buffer can't be full,
-+       * as we will only ever release port we allocated before
-+       */
-+      while (!(HA_ATOMIC_CAS(&range->put_h, &put, GET_NEXT_OFF(range, put))));
-+      HA_ATOMIC_STORE(&range->ports[put], port);
-+      /* Wait until all the threads that got a slot before us are done */
-+      while ((volatile int)range->put_t != put)
-+              __ha_compiler_barrier();
-+      /* Let the world know we're done, and any potential consumer they
-+       * can use that port.
-+       */
-+      HA_ATOMIC_STORE(&range->put_t, GET_NEXT_OFF(range, put));
- }
- /* return a new initialized port range of N ports. The ports are not
-@@ -62,8 +80,10 @@ static inline struct port_range *port_range_alloc_range(int n)
- {
-       struct port_range *ret;
-       ret = calloc(1, sizeof(struct port_range) +
--                   n * sizeof(((struct port_range *)0)->ports[0]));
--      ret->size = ret->avail = n;
-+                   (n + 1) * sizeof(((struct port_range *)0)->ports[0]));
-+      ret->size = n + 1;
-+      /* Start at the first free element */
-+      ret->put_h = ret->put_t = n;
-       return ret;
- }
-diff --git a/include/types/port_range.h b/include/types/port_range.h
-index 1d010f77..33455d2d 100644
---- a/include/types/port_range.h
-+++ b/include/types/port_range.h
-@@ -25,8 +25,7 @@
- #include <netinet/in.h>
- struct port_range {
--      int size, get, put;             /* range size, and get/put positions */
--      int avail;                      /* number of available ports left */
-+      int size, get, put_h, put_t;    /* range size, and get/put positions */
-       uint16_t ports[0];              /* array of <size> ports, in host byte order */
- };
diff --git a/net/haproxy/patches/012-deprecated-openssl.patch b/net/haproxy/patches/012-deprecated-openssl.patch
deleted file mode 100644 (file)
index 8dd011e..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
---- a/src/ssl_sock.c
-+++ b/src/ssl_sock.c
-@@ -39,6 +39,7 @@
- #include <netdb.h>
- #include <netinet/tcp.h>
-+#include <openssl/bn.h>
- #include <openssl/crypto.h>
- #include <openssl/ssl.h>
- #include <openssl/x509.h>
-@@ -60,6 +61,17 @@
- #include <openssl/async.h>
- #endif
-+#ifndef OPENSSL_VERSION
-+#define OPENSSL_VERSION               SSLEAY_VERSION
-+#define OpenSSL_version(x)    SSLeay_version(x)
-+#define OpenSSL_version_num   SSLeay
-+#endif
-+
-+#if OPENSSL_VERSION_NUMBER < 0x10100000L
-+#define X509_getm_notBefore X509_get_notBefore
-+#define X509_getm_notAfter X509_get_notAfter
-+#endif
-+
- #include <import/lru.h>
- #include <import/xxhash.h>
-@@ -217,7 +229,7 @@ static struct {
-       .capture_cipherlist = 0,
- };
--#ifdef USE_THREAD
-+#if defined(USE_THREAD) && (OPENSSL_VERSION_NUMBER < 0x10100000L)
- static HA_RWLOCK_T *ssl_rwlocks;
-@@ -1716,8 +1728,8 @@ ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL
-       ASN1_INTEGER_set(X509_get_serialNumber(newcrt), HA_ATOMIC_ADD(&ssl_ctx_serial, 1));
-       /* Set duration for the certificate */
--      if (!X509_gmtime_adj(X509_get_notBefore(newcrt), (long)-60*60*24) ||
--          !X509_gmtime_adj(X509_get_notAfter(newcrt),(long)60*60*24*365))
-+      if (!X509_gmtime_adj(X509_getm_notBefore(newcrt), (long)-60*60*24) ||
-+          !X509_gmtime_adj(X509_getm_notAfter(newcrt),(long)60*60*24*365))
-               goto mkcert_error;
-       /* set public key in the certificate */
-@@ -6299,7 +6311,7 @@ smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char
-               goto out;
-       smp_trash = get_trash_chunk();
--      if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
-+      if (ssl_sock_get_time(X509_getm_notAfter(crt), smp_trash) <= 0)
-               goto out;
-       smp->data.u.str = *smp_trash;
-@@ -6399,7 +6411,7 @@ smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char
-               goto out;
-       smp_trash = get_trash_chunk();
--      if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
-+      if (ssl_sock_get_time(X509_getm_notBefore(crt), smp_trash) <= 0)
-               goto out;
-       smp->data.u.str = *smp_trash;
-@@ -8976,10 +8988,12 @@ static void __ssl_sock_init(void)
- #endif
-       xprt_register(XPRT_SSL, &ssl_sock);
-+#if OPENSSL_VERSION_NUMBER < 0x10100000L
-       SSL_library_init();
-+#endif
-       cm = SSL_COMP_get_compression_methods();
-       sk_SSL_COMP_zero(cm);
--#ifdef USE_THREAD
-+#if defined(USE_THREAD) && (OPENSSL_VERSION_NUMBER < 0x10100000L)
-       ssl_locking_init();
- #endif
- #if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
-@@ -9008,8 +9022,8 @@ static void __ssl_sock_init(void)
- #else /* OPENSSL_IS_BORINGSSL */
-               OPENSSL_VERSION_TEXT
-               "\nRunning on OpenSSL version : %s%s",
--             SSLeay_version(SSLEAY_VERSION),
--             ((OPENSSL_VERSION_NUMBER ^ SSLeay()) >> 8) ? " (VERSIONS DIFFER!)" : "");
-+             OpenSSL_version(OPENSSL_VERSION),
-+             ((OPENSSL_VERSION_NUMBER ^ OpenSSL_version_num()) >> 8) ? " (VERSIONS DIFFER!)" : "");
- #endif
-       memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
- #if OPENSSL_VERSION_NUMBER < 0x00907000L
-@@ -9100,12 +9114,14 @@ static void __ssl_sock_deinit(void)
-       }
- #endif
-+#if OPENSSL_VERSION_NUMBER < 0x10100000L
-         ERR_remove_state(0);
-         ERR_free_strings();
-         EVP_cleanup();
-+#endif
--#if OPENSSL_VERSION_NUMBER >= 0x00907000L
-+#if OPENSSL_VERSION_NUMBER >= 0x00907000L && OPENSSL_VERSION_NUMBER < 0x10100000L
-         CRYPTO_cleanup_all_ex_data();
- #endif
- }