diff --git a/net/haproxy/Makefile b/net/haproxy/Makefile index 5d10824a02..cf4b892320 100644 --- a/net/haproxy/Makefile +++ b/net/haproxy/Makefile @@ -10,12 +10,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=haproxy -PKG_VERSION:=1.8.20 +PKG_VERSION:=1.8.21 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_HASH:=34bc80bbaab6edae80add1e8b321636e50ccc56cb583040d98d5d245570680e1 PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(BUILD_VARIANT)/$(PKG_NAME)-$(PKG_VERSION) PKG_LICENSE:=GPL-2.0 diff --git a/net/haproxy/get-latest-patches.sh b/net/haproxy/get-latest-patches.sh index f4b683ecf0..7a73468cf9 100755 --- a/net/haproxy/get-latest-patches.sh +++ b/net/haproxy/get-latest-patches.sh @@ -1,7 +1,7 @@ #!/bin/bash CLONEURL=http://git.haproxy.org/git/haproxy-1.8.git -BASE_TAG=v1.8.20 +BASE_TAG=v1.8.21 TMP_REPODIR=tmprepo PATCHESDIR=patches 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 index 4449df1ccd..0000000000 --- a/net/haproxy/patches/000-BUG-MINOR-http-Call-stream_inc_be_http_req_ctr-only-one-time-per-request.patch +++ /dev/null @@ -1,40 +0,0 @@ -commit cf2f1243373be97249567ffd259e975cc87068b8 -Author: Christopher Faulet -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 - (cherry picked from commit 319921866ea9ecc46215fea5679abc8efdfcbea5) - [cf: HTX part was removed] - Signed-off-by: Christopher Faulet - -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/000-BUILD-MINOR-stream-avoid-a-build-warning-with-threads-disabled.patch b/net/haproxy/patches/000-BUILD-MINOR-stream-avoid-a-build-warning-with-threads-disabled.patch new file mode 100644 index 0000000000..f13ac30cb8 --- /dev/null +++ b/net/haproxy/patches/000-BUILD-MINOR-stream-avoid-a-build-warning-with-threads-disabled.patch @@ -0,0 +1,33 @@ +commit db95dd53f88bb15e288b553de5c6687260756f03 +Author: Willy Tarreau +Date: Tue Feb 12 10:59:32 2019 +0100 + + BUILD/MINOR: stream: avoid a build warning with threads disabled + + gcc 6+ complains about a possible null-deref here due to the test in + objt_server() : + + if (objt_server(s->target)) + HA_ATOMIC_ADD(&objt_server(s->target)->counters.retries, 1); + + Let's simply change it to __objt_server(). This can be backported to + 1.9 and 1.8. + + (cherry picked from commit 1ef724e2169eaff7f0272278c3fba9b34d5c7f78) + Signed-off-by: Willy Tarreau + (cherry picked from commit 3d3b67f1877718abbbc8cc500aae373640e454e9) + Signed-off-by: Willy Tarreau + +diff --git a/src/stream.c b/src/stream.c +index f443cc74..99a133a9 100644 +--- a/src/stream.c ++++ b/src/stream.c +@@ -746,7 +746,7 @@ static int sess_update_st_cer(struct stream *s) + si->state = SI_ST_REQ; + } else { + if (objt_server(s->target)) +- HA_ATOMIC_ADD(&objt_server(s->target)->counters.retries, 1); ++ HA_ATOMIC_ADD(&__objt_server(s->target)->counters.retries, 1); + HA_ATOMIC_ADD(&s->be->be_counters.retries, 1); + si->state = SI_ST_ASS; + } 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 index 9ef9507652..0000000000 --- a/net/haproxy/patches/001-BUG-MEDIUM-spoe-arg-len-encoded-in-previous-frag-frame-but-len-changed.patch +++ /dev/null @@ -1,83 +0,0 @@ -commit c1620a52a3def02b4837376385c416c03ca874c4 -Author: Kevin Zhu -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 - (cherry picked from commit 3a838e526cdbc00ded5362e66f1ef3a441abc3c1) - Signed-off-by: Christopher Faulet - -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 from which to resume encoding */ - unsigned int curoff; /* offset in from which to resume encoding */ -+ unsigned int curlen; /* length of 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-haproxy-fix-rule--file-memory-leak.patch b/net/haproxy/patches/001-BUG-MINOR-haproxy-fix-rule--file-memory-leak.patch new file mode 100644 index 0000000000..620b27f866 --- /dev/null +++ b/net/haproxy/patches/001-BUG-MINOR-haproxy-fix-rule--file-memory-leak.patch @@ -0,0 +1,32 @@ +commit ccb3136727d1fd5efccd4689199aa29f530f6ed0 +Author: Dragan Dosen +Date: Tue Apr 30 00:38:36 2019 +0200 + + BUG/MINOR: haproxy: fix rule->file memory leak + + When using the "use_backend" configuration directive, the configuration + file name stored as rule->file was not freed in some situations. This + was introduced in commit 4ed1c95 ("MINOR: http/conf: store the + use_backend configuration file and line for logs"). + + This patch should be backported to 1.9, 1.8 and 1.7. + + (cherry picked from commit 2a7c20f602e5d40e9f23c703fbcb12e3af762337) + Signed-off-by: Willy Tarreau + (cherry picked from commit 60277d1a38b45b014478d33627a9bbb99cc9ee9e) + Signed-off-by: Willy Tarreau + +diff --git a/src/haproxy.c b/src/haproxy.c +index 6ea17a0c..61169243 100644 +--- a/src/haproxy.c ++++ b/src/haproxy.c +@@ -2123,8 +2123,8 @@ void deinit(void) + if (rule->cond) { + prune_acl_cond(rule->cond); + free(rule->cond); +- free(rule->file); + } ++ free(rule->file); + free(rule); + } + diff --git a/net/haproxy/patches/002-MINOR-connection-add-new-function-conn_is_back.patch b/net/haproxy/patches/002-MINOR-connection-add-new-function-conn_is_back.patch new file mode 100644 index 0000000000..afbafd86db --- /dev/null +++ b/net/haproxy/patches/002-MINOR-connection-add-new-function-conn_is_back.patch @@ -0,0 +1,33 @@ +commit a196f480348402a263aa65eed55261e9a59d2da7 +Author: Willy Tarreau +Date: Thu Sep 6 14:52:21 2018 +0200 + + MINOR: connection: add new function conn_is_back() + + This function returns true if the connection is a backend connection + and false if it's a frontend connection. + + (cherry picked from commit 57f8185625f967f868187d336f995fac28f83fc5) + [wt: backported since used by next commit] + Signed-off-by: Willy Tarreau + +diff --git a/include/proto/connection.h b/include/proto/connection.h +index 352f2fcc..31e746a1 100644 +--- a/include/proto/connection.h ++++ b/include/proto/connection.h +@@ -912,6 +912,15 @@ static inline const struct mux_ops *alpn_get_mux(const struct ist token, int htt + return fallback; + } + ++/* returns 0 if the connection is valid and is a frontend connection, otherwise ++ * returns 1 indicating it's a backend connection. And uninitialized connection ++ * also returns 1 to better handle the usage in the middle of initialization. ++ */ ++static inline int conn_is_back(const struct connection *conn) ++{ ++ return !objt_listener(conn->target); ++} ++ + /* finds the best mux for incoming connection and mode for + * the proxy. Null cannot be returned unless there's a serious bug somewhere + * else (no fallback mux registered). 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 index c26629c816..0000000000 --- a/net/haproxy/patches/002-MINOR-spoe-Use-the-sample-context-to-pass-frag_ctx-info-during-encoding.patch +++ /dev/null @@ -1,71 +0,0 @@ -commit 72fdff1fdb5b82685dc3d2db23ece042195a0cbd -Author: Christopher Faulet -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 - (cherry picked from commit b93366e3ee44f5de93f01569fcdcd602f6d0703f) - Signed-off-by: Christopher Faulet - -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-ssl-Use-the-early_data-API-the-right-way.patch b/net/haproxy/patches/003-BUG-MEDIUM-ssl-Use-the-early_data-API-the-right-way.patch new file mode 100644 index 0000000000..ab343f09bf --- /dev/null +++ b/net/haproxy/patches/003-BUG-MEDIUM-ssl-Use-the-early_data-API-the-right-way.patch @@ -0,0 +1,77 @@ +commit ad838cae47c15dc0be018be6c081e241d41ed45f +Author: Olivier Houchard +Date: Fri May 3 20:56:19 2019 +0200 + + BUG/MEDIUM: ssl: Use the early_data API the right way. + + We can only read early data if we're a server, and write if we're a client, + so don't attempt to mix both. + + This should be backported to 1.8 and 1.9. + + (cherry picked from commit 010941f87605e8219d25becdbc652350a687d6a2) + [wt: minor context adjustments due to latest SSL API changes in 2.0] + Signed-off-by: Willy Tarreau + (cherry picked from commit 3d14cbddd971f8f301f795c8446ae2bcadab6cc2) + Signed-off-by: Willy Tarreau + +diff --git a/src/backend.c b/src/backend.c +index 0cf14cfd..c43fb72f 100644 +--- a/src/backend.c ++++ b/src/backend.c +@@ -1214,10 +1214,8 @@ int connect_server(struct stream *s) + (srv->ssl_ctx.options & SRV_SSL_O_EARLY_DATA) && + (cli_conn->flags & CO_FL_EARLY_DATA) && + !channel_is_empty(si_oc(&s->si[1])) && +- srv_conn->flags & CO_FL_SSL_WAIT_HS) { ++ srv_conn->flags & CO_FL_SSL_WAIT_HS) + srv_conn->flags &= ~(CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN); +- srv_conn->flags |= CO_FL_EARLY_SSL_HS; +- } + #endif + + if (err != SF_ERR_NONE) +diff --git a/src/ssl_sock.c b/src/ssl_sock.c +index 1fc01c1c..76767242 100644 +--- a/src/ssl_sock.c ++++ b/src/ssl_sock.c +@@ -5549,7 +5549,7 @@ static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int fl + if (!conn->xprt_ctx) + goto out_error; + +- if (conn->flags & CO_FL_HANDSHAKE) ++ if (conn->flags & (CO_FL_HANDSHAKE | CO_FL_EARLY_SSL_HS)) + /* a handshake was requested */ + return 0; + +@@ -5578,7 +5578,7 @@ static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int fl + } + + #if (OPENSSL_VERSION_NUMBER >= 0x10101000L) +- if (!SSL_is_init_finished(conn->xprt_ctx)) { ++ if (!SSL_is_init_finished(conn->xprt_ctx) && conn_is_back(conn)) { + unsigned int max_early; + + if (objt_listener(conn->target)) +@@ -5593,8 +5593,7 @@ static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int fl + if (try + conn->sent_early_data > max_early) { + try -= (try + conn->sent_early_data) - max_early; + if (try <= 0) { +- if (!(conn->flags & CO_FL_EARLY_SSL_HS)) +- conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN; ++ conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN; + break; + } + } +@@ -5602,10 +5601,8 @@ static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int fl + if (ret == 1) { + ret = written_data; + conn->sent_early_data += ret; +- if (objt_server(conn->target)) { +- conn->flags &= ~CO_FL_EARLY_SSL_HS; ++ if (objt_server(conn->target)) + conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_EARLY_DATA; +- } + + } + 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 index 514c4c568d..0000000000 --- a/net/haproxy/patches/003-DOC-contrib-modsecurity-Typos-and-fix-the-reject-example.patch +++ /dev/null @@ -1,38 +0,0 @@ -commit dfc3718f0a302ea3deb5f1a325d35fce0e4cfa48 -Author: Yann Cézard -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 - (cherry picked from commit 850896603086877641272d6e4075e66bd91f2e50) - Signed-off-by: Christopher Faulet - -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-checks-make-sure-the-warmup-task-takes-the-server-lock.patch b/net/haproxy/patches/004-BUG-MEDIUM-checks-make-sure-the-warmup-task-takes-the-server-lock.patch new file mode 100644 index 0000000000..086fd93e73 --- /dev/null +++ b/net/haproxy/patches/004-BUG-MEDIUM-checks-make-sure-the-warmup-task-takes-the-server-lock.patch @@ -0,0 +1,39 @@ +commit ae6824e2c836f1714827e9d3f585e729ea022f30 +Author: Willy Tarreau +Date: Sun May 5 06:54:22 2019 +0200 + + BUG/MEDIUM: checks: make sure the warmup task takes the server lock + + The server warmup task is used when a server uses the "slowstart" + parameter. This task affects the server's weight and maxconn, and may + dequeue pending connections from the queue. This must be done under + the server's lock, which was not the case. + + This must be backported to 1.9 and 1.8. + + (cherry picked from commit 4fc49a9aabacc8028877e2dcbdb54d8a19c398c4) + Signed-off-by: Willy Tarreau + (cherry picked from commit 207ba5a6bc1c03f2ba15ac3cd49bfa756fb760bb) + Signed-off-by: Willy Tarreau + +diff --git a/src/checks.c b/src/checks.c +index 1ecc4050..fbe14ca1 100644 +--- a/src/checks.c ++++ b/src/checks.c +@@ -1445,12 +1445,16 @@ static struct task *server_warmup(struct task *t) + (s->next_state != SRV_ST_STARTING)) + return t; + ++ HA_SPIN_LOCK(SERVER_LOCK, &s->lock); ++ + /* recalculate the weights and update the state */ + server_recalc_eweight(s); + + /* probably that we can refill this server with a bit more connections */ + pendconn_grab_from_px(s); + ++ HA_SPIN_UNLOCK(SERVER_LOCK, &s->lock); ++ + /* get back there in 1 second or 1/20th of the slowstart interval, + * whichever is greater, resulting in small 5% steps. + */ 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 index af49cc2f41..0000000000 --- a/net/haproxy/patches/004-BUG-MEDIUM-contrib-modsecurity-If-host-header-is-NULL-dont-try-to-strdup-it.patch +++ /dev/null @@ -1,36 +0,0 @@ -commit 95cf225d099dcb49eefcf4f5b648be604414ae0c -Author: Yann Cézard -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 - (cherry picked from commit d988e3dddcbe1f48f3b24d1bb529fc9ecefde180) - Signed-off-by: Christopher Faulet - -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/005-BUG-MINOR-logs-threads-properly-split-the-log-area-upon-startup.patch b/net/haproxy/patches/005-BUG-MINOR-logs-threads-properly-split-the-log-area-upon-startup.patch new file mode 100644 index 0000000000..5e5caa354b --- /dev/null +++ b/net/haproxy/patches/005-BUG-MINOR-logs-threads-properly-split-the-log-area-upon-startup.patch @@ -0,0 +1,108 @@ +commit dc90debd638a2aa94e062e66c00b1b8a9ab3c115 +Author: Willy Tarreau +Date: Sun May 5 10:11:39 2019 +0200 + + BUG/MINOR: logs/threads: properly split the log area upon startup + + If logs were emitted before creating the threads, then the dataptr pointer + keeps a copy of the end of the log header. Then after the threads are + created, the headers are reallocated for each thread. However the end + pointer was not reset until the end of the first second, which may result + in logs emitted by multiple threads during the first second to be mangled, + or possibly in some cases to use a memory area that was reused for something + else. The fix simply consists in reinitializing the end pointers immediately + when the threads are created. + + This fix must be backported to 1.9 and 1.8. + + (cherry picked from commit 55e2f5ad14a6d9ec39c218296ad3f1a521cc74a1) + Signed-off-by: Willy Tarreau + (cherry picked from commit 55c3bd480fbbbb4692368655d3d4a425b5248e2a) + [wt: ctx, buf->chunk] + Signed-off-by: Willy Tarreau + +diff --git a/src/log.c b/src/log.c +index 313fa55d..1d8cf335 100644 +--- a/src/log.c ++++ b/src/log.c +@@ -212,11 +212,13 @@ char default_rfc5424_sd_log_format[] = "- "; + * update_log_hdr(). + */ + THREAD_LOCAL char *logheader = NULL; ++THREAD_LOCAL char *logheader_end = NULL; + + /* This is a global syslog header for messages in RFC5424 format. It is + * updated by update_log_hdr_rfc5424(). + */ + THREAD_LOCAL char *logheader_rfc5424 = NULL; ++THREAD_LOCAL char *logheader_rfc5424_end = NULL; + + /* This is a global syslog message buffer, common to all outgoing + * messages. It contains only the data part. +@@ -986,11 +988,10 @@ char *lf_port(char *dst, struct sockaddr *sockaddr, size_t size, struct logforma + static char *update_log_hdr(const time_t time) + { + static THREAD_LOCAL long tvsec; +- static THREAD_LOCAL char *dataptr = NULL; /* backup of last end of header, NULL first time */ + static THREAD_LOCAL struct chunk host = { NULL, 0, 0 }; + static THREAD_LOCAL int sep = 0; + +- if (unlikely(time != tvsec || dataptr == NULL)) { ++ if (unlikely(time != tvsec || logheader_end == NULL)) { + /* this string is rebuild only once a second */ + struct tm tm; + int hdr_len; +@@ -1016,12 +1017,12 @@ static char *update_log_hdr(const time_t time) + if (hdr_len < 0 || hdr_len > global.max_syslog_len) + hdr_len = global.max_syslog_len; + +- dataptr = logheader + hdr_len; ++ logheader_end = logheader + hdr_len; + } + +- dataptr[0] = 0; // ensure we get rid of any previous attempt ++ logheader_end[0] = 0; // ensure we get rid of any previous attempt + +- return dataptr; ++ return logheader_end; + } + + /* Re-generate time-based part of the syslog header in RFC5424 format at +@@ -1031,10 +1032,9 @@ static char *update_log_hdr(const time_t time) + static char *update_log_hdr_rfc5424(const time_t time) + { + static THREAD_LOCAL long tvsec; +- static THREAD_LOCAL char *dataptr = NULL; /* backup of last end of header, NULL first time */ + const char *gmt_offset; + +- if (unlikely(time != tvsec || dataptr == NULL)) { ++ if (unlikely(time != tvsec || logheader_rfc5424_end == NULL)) { + /* this string is rebuild only once a second */ + struct tm tm; + int hdr_len; +@@ -1056,12 +1056,12 @@ static char *update_log_hdr_rfc5424(const time_t time) + if (hdr_len < 0 || hdr_len > global.max_syslog_len) + hdr_len = global.max_syslog_len; + +- dataptr = logheader_rfc5424 + hdr_len; ++ logheader_rfc5424_end = logheader_rfc5424 + hdr_len; + } + +- dataptr[0] = 0; // ensure we get rid of any previous attempt ++ logheader_rfc5424_end[0] = 0; // ensure we get rid of any previous attempt + +- return dataptr; ++ return logheader_rfc5424_end; + } + + /* +@@ -1369,7 +1369,9 @@ static void deinit_log_buffers_per_thread() + int init_log_buffers() + { + logheader = my_realloc2(logheader, global.max_syslog_len + 1); ++ logheader_end = NULL; + logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1); ++ logheader_rfc5424_end = NULL; + logline = my_realloc2(logline, global.max_syslog_len + 1); + logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1); + if (!logheader || !logline_rfc5424 || !logline || !logline_rfc5424) 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 index 310dc0f4f4..0000000000 --- a/net/haproxy/patches/005-MINOR-examples-Use-right-locale-for-the-last-changelog-date-in-haproxy-spec.patch +++ /dev/null @@ -1,23 +0,0 @@ -commit 86860896dc1841eb59cb95832d76a8093e8dc8c5 -Author: Christopher Faulet -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 -+* Thu Apr 25 2019 Christopher Faulet - - updated to 1.8.20 - - * Mon Feb 11 2019 Willy Tarreau 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 index e961294770..0000000000 --- a/net/haproxy/patches/006-BUG-MAJOR-map-acl-real-fix-segfault-during-show-map-acl-on-CLI.patch +++ /dev/null @@ -1,67 +0,0 @@ -commit 83af1f6b65806982640679823228976deebf5202 -Author: Willy Tarreau -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 - (cherry picked from commit ac4be10f62ef72962d9cf0e6f2619e1e1c370d62) - Signed-off-by: Christopher Faulet - -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-MINOR-doc-Document-allow-0rtt-on-the-server-line.patch b/net/haproxy/patches/006-MINOR-doc-Document-allow-0rtt-on-the-server-line.patch new file mode 100644 index 0000000000..525b6b4442 --- /dev/null +++ b/net/haproxy/patches/006-MINOR-doc-Document-allow-0rtt-on-the-server-line.patch @@ -0,0 +1,32 @@ +commit b6aa92725eaf823c4b18316729eae494783daa85 +Author: Olivier Houchard +Date: Mon May 6 18:58:48 2019 +0200 + + MINOR: doc: Document allow-0rtt on the server line. + + Briefly document allow-0rtt on the server line, and only the part that apply + to 1.8 and 1.9. + + This should be backported to 1.8 and 1.9. + + (cherry picked from commit 8cb2d2e94199b8a6a9186ec12ee8146421a5d227) + Signed-off-by: Willy Tarreau + (cherry picked from commit 895b6a4568287b87d69599f347da01dcd1cfc9b2) + [wt: context] + Signed-off-by: Willy Tarreau + +diff --git a/doc/configuration.txt b/doc/configuration.txt +index 7768e761..720b32e3 100644 +--- a/doc/configuration.txt ++++ b/doc/configuration.txt +@@ -11223,6 +11223,10 @@ agent-port + + See also the "agent-check" and "agent-inter" parameters. + ++allow-0rtt ++ Allow sending early data to the server when using TLS 1.3. ++ Note that early data will be sent only if the client used early data. ++ + backup + When "backup" is present on a server line, the server is only used in load + balancing when all other non-backup servers are unavailable. Requests coming 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 index e54c530fbe..0000000000 --- a/net/haproxy/patches/007-BUG-MEDIUM-listener-Fix-how-unlimited-number-of-consecutive-accepts-is-handled.patch +++ /dev/null @@ -1,79 +0,0 @@ -commit 7bd7a8d2b8889f604b807c21190d2e70328d6674 -Author: Christopher Faulet -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 - (cherry picked from commit bca4fb2d9d7f2966d9f8270fa1796fdc0dfc866d) - Signed-off-by: Christopher Faulet - -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-spoe-Be-sure-the-sample-is-found-before-setting-its-context.patch b/net/haproxy/patches/007-BUG-MEDIUM-spoe-Be-sure-the-sample-is-found-before-setting-its-context.patch new file mode 100644 index 0000000000..b1e101ec6a --- /dev/null +++ b/net/haproxy/patches/007-BUG-MEDIUM-spoe-Be-sure-the-sample-is-found-before-setting-its-context.patch @@ -0,0 +1,50 @@ +commit dcb8c973fdfa6b96b651b06740b74b1d492cb92d +Author: Christopher Faulet +Date: Mon May 6 09:53:10 2019 +0200 + + BUG/MEDIUM: spoe: Be sure the sample is found before setting its context + + When a sample fetch is encoded, we use its context to set info about the + fragmentation. But if the sample is not found, the function sample_process() + returns NULL. So we me be sure the sample exists before setting its context. + + This patch must be backported to 1.9 and 1.8. + + (cherry picked from commit 3b1d004d410129efcf365643d2583dcd2cb6ed0f) + Signed-off-by: Willy Tarreau + (cherry picked from commit 2e062883b8f94500314b7c863c1a13e3c9af23ca) + [wt: adjust buf->chunk context] + Signed-off-by: Willy Tarreau + +diff --git a/include/proto/spoe.h b/include/proto/spoe.h +index cce13e50..74fe9466 100644 +--- a/include/proto/spoe.h ++++ b/include/proto/spoe.h +@@ -169,8 +169,8 @@ spoe_encode_data(struct sample *smp, char **buf, char *end) + * 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); ++ unsigned int *len = smp->ctx.a[0]; ++ unsigned int *off = smp->ctx.a[1]; + + if (!*off) { + /* First evaluation of the sample : encode the +diff --git a/src/flt_spoe.c b/src/flt_spoe.c +index aeb1fde7..9f745943 100644 +--- a/src/flt_spoe.c ++++ b/src/flt_spoe.c +@@ -2187,8 +2187,10 @@ 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); +- smp->ctx.a[0] = &ctx->frag_ctx.curlen; +- smp->ctx.a[1] = &ctx->frag_ctx.curoff; ++ if (smp) { ++ 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/008-DOC-fixed-typo-in-management-txt.patch b/net/haproxy/patches/008-DOC-fixed-typo-in-management-txt.patch new file mode 100644 index 0000000000..3cc4d2bf07 --- /dev/null +++ b/net/haproxy/patches/008-DOC-fixed-typo-in-management-txt.patch @@ -0,0 +1,31 @@ +commit 42c7b87b18bce3a12a8b1a08435e393ed543f79f +Author: n9@users.noreply.github.com +Date: Fri Aug 23 11:21:05 2019 +0200 + + DOC: fixed typo in management.txt + + replaced fot -> for + added two periods + + (cherry picked from commit 25a1c8e4539c12c19a3fe04aabe563cdac5e36db) + Signed-off-by: Willy Tarreau + (cherry picked from commit 7c80af0fb53f2a1d93a597f7d97cc67996e36be2) + Signed-off-by: Willy Tarreau + (cherry picked from commit 4c43256c7e78643f8972f4248ed11688137609bb) + Signed-off-by: Willy Tarreau + +diff --git a/doc/management.txt b/doc/management.txt +index 8fdea722..e79b3cd0 100644 +--- a/doc/management.txt ++++ b/doc/management.txt +@@ -1483,8 +1483,8 @@ enable agent / + level "admin". + + enable dynamic-cookie backend +- Enable the generation of dynamic cookies fot the backend +- A secret key must also be provided ++ Enable the generation of dynamic cookies for the backend . ++ A secret key must also be provided. + + enable frontend + Resume a frontend which was temporarily stopped. It is possible that some of 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 index 5c5d88967a..0000000000 --- a/net/haproxy/patches/008-MINOR-config-Test-validity-of-tune-maxaccept-during-the-config-parsing.patch +++ /dev/null @@ -1,44 +0,0 @@ -commit 6e580b6e744011e87c337ebe2c082acfd5ca835a -Author: Christopher Faulet -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 - (cherry picked from commit 2bbc40f8bc9a52ba0d03b25270ac0129cca29bba) - Signed-off-by: Christopher Faulet - -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-BUG-MINOR-mworker-disable-SIGPROF-on-re-exec.patch b/net/haproxy/patches/009-BUG-MINOR-mworker-disable-SIGPROF-on-re-exec.patch new file mode 100644 index 0000000000..a19498f564 --- /dev/null +++ b/net/haproxy/patches/009-BUG-MINOR-mworker-disable-SIGPROF-on-re-exec.patch @@ -0,0 +1,39 @@ +commit 7ae43ca14823ae61c547ac08c0a237b6ec55e04a +Author: Willy Tarreau +Date: Mon Aug 26 10:37:39 2019 +0200 + + BUG/MINOR: mworker: disable SIGPROF on re-exec + + If haproxy is built with profiling enabled with -pg, it is possible to + see the master quit during a reload while it's re-executing itself with + error code 155 (signal 27) saying "Profile timer expired)". This happens + if the SIGPROF signal is delivered during the execve() call while the + handler was already unregistered. The issue itself is not directly inside + haproxy but it's easy to address. This patch disables this signal before + calling execvp() during a master reload. A simple test for this consists + in running this little script with haproxy started in master-worker mode : + + $ while usleep 50000; do killall -USR2 haproxy; done + + This fix should be backported to all versions using the master-worker + model. + + (cherry picked from commit e0d86e2c1caaaa2141118e3309d479de5f67e855) + Signed-off-by: Willy Tarreau + (cherry picked from commit f259fcc00a04e633a7a64f894a719f78f3644867) + Signed-off-by: Willy Tarreau + (cherry picked from commit f2c9971cb51d28f0c4422d1197447406aa72e945) + Signed-off-by: Willy Tarreau + +diff --git a/src/haproxy.c b/src/haproxy.c +index 61169243..ef5a05cc 100644 +--- a/src/haproxy.c ++++ b/src/haproxy.c +@@ -705,6 +705,7 @@ static void mworker_reload() + } + + ha_warning("Reexecuting Master process\n"); ++ signal(SIGPROF, SIG_IGN); + execvp(next_argv[0], next_argv); + + ha_warning("Failed to reexecute the master process [%d]: %s\n", pid, strerror(errno)); 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 index 4bcae444fe..0000000000 --- a/net/haproxy/patches/009-CLEANUP-config-Dont-alter-listener--maxaccept-when-nbproc-is-set-to-1.patch +++ /dev/null @@ -1,34 +0,0 @@ -commit c6e03c1495fa51f9a98ed0bbe3230313c7c7201c -Author: Christopher Faulet -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 - (cherry picked from commit 14203e3cf9404e57de5e274b453f0fe4f2174924) - Signed-off-by: Christopher Faulet - -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-BUG-MEDIUM-listener-threads-fix-an-AB-BA-locking-issue-in-delete_listener.patch b/net/haproxy/patches/010-BUG-MEDIUM-listener-threads-fix-an-AB-BA-locking-issue-in-delete_listener.patch new file mode 100644 index 0000000000..17dd3d42d6 --- /dev/null +++ b/net/haproxy/patches/010-BUG-MEDIUM-listener-threads-fix-an-AB-BA-locking-issue-in-delete_listener.patch @@ -0,0 +1,57 @@ +commit ae9e97ed9d2ac46515e0fba1cb71028169cc3be6 +Author: Willy Tarreau +Date: Mon Aug 26 10:55:52 2019 +0200 + + BUG/MEDIUM: listener/threads: fix an AB/BA locking issue in delete_listener() + + The delete_listener() function takes the listener's lock before taking + the proto_lock, which is contrary to what other functions do, possibly + causing an AB/BA deadlock. In practice the two only places where both + are taken are during protocol_enable_all() and delete_listener(), the + former being used during startup and the latter during stop. In practice + during reload floods, it is technically possible for a thread to be + initializing the listeners while another one is stopping. While this + is too hard to trigger on 2.0 and above due to the synchronization of + all threads during startup, it's reasonably easy to do in 1.9 by having + hundreds of listeners, starting 64 threads and flooding them with reloads + like this : + + $ while usleep 50000; do killall -USR2 haproxy; done + + Usually in less than a minute, all threads will be deadlocked. The fix + consists in always taking the proto_lock before the listener lock. It + seems to be the only place where these two locks were reversed. This + fix needs to be backported to 2.0, 1.9, and 1.8. + + (cherry picked from commit 6ee9f8df3bfbb811526cff3313da5758b1277bc6) + Signed-off-by: Willy Tarreau + (cherry picked from commit b10c8d7641cc8ceae6fba4506b7f987d66109bd9) + [wt: adjusted context] + Signed-off-by: Willy Tarreau + (cherry picked from commit bf64d1021bd0db1f9892ec34473e34033cdb1dd9) + Signed-off-by: Willy Tarreau + +diff --git a/src/listener.c b/src/listener.c +index 9832794d..92cc0f75 100644 +--- a/src/listener.c ++++ b/src/listener.c +@@ -424,17 +424,17 @@ int create_listeners(struct bind_conf *bc, const struct sockaddr_storage *ss, + */ + void delete_listener(struct listener *listener) + { ++ HA_SPIN_LOCK(PROTO_LOCK, &proto_lock); + HA_SPIN_LOCK(LISTENER_LOCK, &listener->lock); + if (listener->state == LI_ASSIGNED) { + listener->state = LI_INIT; +- HA_SPIN_LOCK(PROTO_LOCK, &proto_lock); + LIST_DEL(&listener->proto_list); + listener->proto->nb_listeners--; +- HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock); + HA_ATOMIC_SUB(&jobs, 1); + HA_ATOMIC_SUB(&listeners, 1); + } + HA_SPIN_UNLOCK(LISTENER_LOCK, &listener->lock); ++ HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock); + } + + /* This function is called on a read event from a listening socket, corresponding 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 index 30e8cd4d72..0000000000 --- a/net/haproxy/patches/010-MINOR-threads-Implement-HA_ATOMIC_LOAD.patch +++ /dev/null @@ -1,54 +0,0 @@ -commit f95cf6ad70565ee2322cf23bc519b7bb0b3831b2 -Author: Olivier Houchard -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 - (cherry picked from commit 358c979611370fa2bc3b8e47ed50a325cf9126cf) - Signed-off-by: Christopher Faulet - -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 index 68332fdde4..0000000000 --- a/net/haproxy/patches/011-BUG-MEDIUM-port_range-Make-the-ring-buffer-lock-free.patch +++ /dev/null @@ -1,116 +0,0 @@ -commit 31470e2ba2aabb4c6340fbc15cb5486ceb8c69c8 -Author: Olivier Houchard -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 - (cherry picked from commit bffb51147a4a5939e344b3c838628f9a944febef) - Signed-off-by: Christopher Faulet - -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 - -+#define GET_NEXT_OFF(range, off) ((off) == (range)->size - 1 ? 0 : (off) + 1) -+ - /* return an available port from 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 - - 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 ports, in host byte order */ - }; - diff --git a/net/haproxy/patches/011-BUG-MEDIUM-proto-http-Always-start-the-parsing-if-there-is-no-outgoing-data.patch b/net/haproxy/patches/011-BUG-MEDIUM-proto-http-Always-start-the-parsing-if-there-is-no-outgoing-data.patch new file mode 100644 index 0000000000..b7dd95d7b0 --- /dev/null +++ b/net/haproxy/patches/011-BUG-MEDIUM-proto-http-Always-start-the-parsing-if-there-is-no-outgoing-data.patch @@ -0,0 +1,60 @@ +commit ba3abeda541ffe93fd528e9bc8701d4faadfb680 +Author: Christopher Faulet +Date: Wed Sep 4 09:39:42 2019 +0200 + + BUG/MEDIUM: proto-http: Always start the parsing if there is no outgoing data + + When we are waiting for a request or a response, if the channel's buffer is not + rewritable (the reservce is not fully free), nothing is done and we wait to have + a rewritable buffer. It was an old implicit assumption of HTTP analyzers. On old + versions, at this stage, if a buffer was not rewritable, it meant some outgoing + data were pending to be sent. + + On recent versions, it should not happen because all outgoing data are sent + before starting the analysis of the next transaction. But the applets may be + lead to use the reserve. For instance, the cache applet adds the header "Age" to + cached responses. It may use the reserve to do so if the size of the response + headers is huge. So, in such case, the implicit assumption of a no rewritable + buffer because of output data is wrong. But the message analysis remains + blocked, sometime infinitely depending on circumstances. + + To fix the bug and to avoid any ambiguity, we now also check if there are some + outgoing data when the buffer is not rewritable to postpone the message + analysis. In fact, this code may probably be removed because it should never + happen. But I prefer to be conservative here and don't introduce a bug because of + an unknown/unexpected hidden corner case. Anyway, it is not a big deal because + all legacy HTTP code is removed in the 2.1. + + This is a direct commit to the 2.0 branch, as the problem doesn't exist in + master. It must be backported at least to 1.9 and 1.8 because of the cache. But + it may be also backported to all stable versions. + + This patch should partly fix the github issue #233. + + (cherry picked from commit 3d36d4e720a76a12c7f6cd64c7971237d7d92d78) + Signed-off-by: Christopher Faulet + (cherry picked from commit d09d66853a3700d2b9261c02e1027d13b4420f5b) + Signed-off-by: Christopher Faulet + +diff --git a/src/proto_http.c b/src/proto_http.c +index c64ba0ea..411eb698 100644 +--- a/src/proto_http.c ++++ b/src/proto_http.c +@@ -1633,7 +1633,7 @@ int http_wait_for_request(struct stream *s, struct channel *req, int an_bit) + */ + if (buffer_not_empty(req->buf) && msg->msg_state < HTTP_MSG_ERROR) { + if (txn->flags & TX_NOT_FIRST) { +- if (unlikely(!channel_is_rewritable(req))) { ++ if (unlikely(!channel_is_rewritable(req) && req->buf->o)) { + if (req->flags & (CF_SHUTW|CF_SHUTW_NOW|CF_WRITE_ERROR|CF_WRITE_TIMEOUT)) + goto failed_keep_alive; + /* some data has still not left the buffer, wake us once that's done */ +@@ -5102,7 +5102,7 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit) + * data later, which is much more complicated. + */ + if (buffer_not_empty(rep->buf) && msg->msg_state < HTTP_MSG_ERROR) { +- if (unlikely(!channel_is_rewritable(rep))) { ++ if (unlikely(!channel_is_rewritable(rep) && rep->buf->o)) { + /* some data has still not left the buffer, wake us once that's done */ + if (rep->flags & (CF_SHUTW|CF_SHUTW_NOW|CF_WRITE_ERROR|CF_WRITE_TIMEOUT)) + goto abort_response; diff --git a/net/haproxy/patches/012-BUG-MINOR-http_fetch-Rely-on-the-smp-direction-for-cookie-and-hdr.patch b/net/haproxy/patches/012-BUG-MINOR-http_fetch-Rely-on-the-smp-direction-for-cookie-and-hdr.patch deleted file mode 100644 index 3b7e268391..0000000000 --- a/net/haproxy/patches/012-BUG-MINOR-http_fetch-Rely-on-the-smp-direction-for-cookie-and-hdr.patch +++ /dev/null @@ -1,81 +0,0 @@ -commit ef9cafc46c13eea2db65152e452607a6566cbeac -Author: Christopher Faulet -Date: Thu May 16 10:07:30 2019 +0200 - - BUG/MINOR: http_fetch: Rely on the smp direction for "cookie()" and "hdr()" - - A regression was introduced in the commit 89dc49935 ("BUG/MAJOR: http_fetch: Get - the channel depending on the keyword used") on the samples "cookie()" and - "hdr()". Unlike other samples manipulating the HTTP headers, these ones depend - on the sample direction. To fix the bug, these samples use now their own - functions. Depending on the sample direction, they call smp_fetch_cookie() and - smp_fetch_hdr() with the appropriate keyword. - - Thanks to Yves Lafon to report this issue. - - This patch must be backported wherever the commit 89dc49935 was backported. For - now, 1.9 and 1.8. - - (cherry picked from commit c1f40dd4920050ec5a83b2a5d22a3eb4e4be425a) - Signed-off-by: Christopher Faulet - (cherry picked from commit 5eaf770abfce56951202cb1ea55a968f5ec8be71) - Signed-off-by: Christopher Faulet - -diff --git a/src/proto_http.c b/src/proto_http.c -index 556cabad..32aeef2d 100644 ---- a/src/proto_http.c -+++ b/src/proto_http.c -@@ -10218,6 +10218,17 @@ smp_fetch_hdr(const struct arg *args, struct sample *smp, const char *kw, void * - return 0; - } - -+/* Same than smp_fetch_hdr() but only relies on the sample direction to choose -+ * the right channel. So instead of duplicating the code, we just change the -+ * keyword and then fallback on smp_fetch_hdr(). -+ */ -+static int -+smp_fetch_chn_hdr(const struct arg *args, struct sample *smp, const char *kw, void *private) -+{ -+ kw = ((smp->opt & SMP_OPT_DIR) == SMP_OPT_DIR_REQ ? "req.hdr" : "res.hdr"); -+ return smp_fetch_hdr(args, smp, kw, private); -+} -+ - /* 6. Check on HTTP header count. The number of occurrences is returned. - * Accepts exactly 1 argument of type string. - */ -@@ -10935,6 +10946,17 @@ int smp_fetch_cookie(const struct arg *args, struct sample *smp, const char *kw, - return found; - } - -+/* Same than smp_fetch_cookie() but only relies on the sample direction to -+ * choose the right channel. So instead of duplicating the code, we just change -+ * the keyword and then fallback on smp_fetch_cookie(). -+ */ -+static int -+smp_fetch_chn_cookie(const struct arg *args, struct sample *smp, const char *kw, void *private) -+{ -+ kw = ((smp->opt & SMP_OPT_DIR) == SMP_OPT_DIR_REQ ? "req.cook" : "res.cook"); -+ return smp_fetch_cookie(args, smp, kw, private); -+} -+ - /* Iterate over all cookies present in a request to count how many occurrences - * match the name in args and args->data.str.len. If is non-null, then - * multiple cookies may be parsed on the same line. The returned sample is of -@@ -12855,7 +12877,7 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, { - * for ACL compatibility only. - */ - { "cook", smp_fetch_cookie, ARG1(0,STR), NULL, SMP_T_STR, SMP_USE_HRQHV }, -- { "cookie", smp_fetch_cookie, ARG1(0,STR), NULL, SMP_T_STR, SMP_USE_HRQHV|SMP_USE_HRSHV }, -+ { "cookie", smp_fetch_chn_cookie, ARG1(0,STR), NULL, SMP_T_STR, SMP_USE_HRQHV|SMP_USE_HRSHV }, - { "cook_cnt", smp_fetch_cookie_cnt, ARG1(0,STR), NULL, SMP_T_SINT, SMP_USE_HRQHV }, - { "cook_val", smp_fetch_cookie_val, ARG1(0,STR), NULL, SMP_T_SINT, SMP_USE_HRQHV }, - -@@ -12863,7 +12885,7 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, { - * only here to match the ACL's name, are request-only and are used for - * ACL compatibility only. - */ -- { "hdr", smp_fetch_hdr, ARG2(0,STR,SINT), val_hdr, SMP_T_STR, SMP_USE_HRQHV|SMP_USE_HRSHV }, -+ { "hdr", smp_fetch_chn_hdr, ARG2(0,STR,SINT), val_hdr, SMP_T_STR, SMP_USE_HRQHV|SMP_USE_HRSHV }, - { "hdr_cnt", smp_fetch_hdr_cnt, ARG1(0,STR), NULL, SMP_T_SINT, SMP_USE_HRQHV }, - { "hdr_ip", smp_fetch_hdr_ip, ARG2(0,STR,SINT), val_hdr, SMP_T_IPV4, SMP_USE_HRQHV }, - { "hdr_val", smp_fetch_hdr_val, ARG2(0,STR,SINT), val_hdr, SMP_T_SINT, SMP_USE_HRQHV }, diff --git a/net/haproxy/patches/029-deprecated-openssl.patch b/net/haproxy/patches/012-deprecated-openssl.patch similarity index 100% rename from net/haproxy/patches/029-deprecated-openssl.patch rename to net/haproxy/patches/012-deprecated-openssl.patch diff --git a/net/haproxy/patches/013-BUG-MEDIUM-dns-make-the-port-numbers-unsigned.patch b/net/haproxy/patches/013-BUG-MEDIUM-dns-make-the-port-numbers-unsigned.patch deleted file mode 100644 index 830c7672a2..0000000000 --- a/net/haproxy/patches/013-BUG-MEDIUM-dns-make-the-port-numbers-unsigned.patch +++ /dev/null @@ -1,37 +0,0 @@ -commit b50e7fe5e9ae7e8670a467fdd7ece2d08fc02809 -Author: Willy Tarreau -Date: Wed May 22 20:07:45 2019 +0200 - - BUG/MEDIUM: dns: make the port numbers unsigned - - Mustafa Yildirim reported in Discourse that ports >32767 advertised - in SRV records are wrong. Given the high value they definitely - correspond to a sign extension of a negative number. The cause was - indeed that the port is declared as a signed int in the dns_answer_item - structure, and Lukas confirmed in github issue #103 that turning it to - unsigned addresses the issue. - - It is worth noting that there are other such fields in this structure - that don't look right (ttl, priority, class, type) and that someone - should audit this part to be certain they are properly typed. - - This fix must be backported to 1.9 and likely to 1.8 as well. - - (cherry picked from commit d1f56c9a0110805c4a5f3afba2990556cb74ec8b) - Signed-off-by: Christopher Faulet - (cherry picked from commit 01ceb8a9fb0caecb20a12cc6763230cfc9895de5) - Signed-off-by: Christopher Faulet - -diff --git a/include/types/dns.h b/include/types/dns.h -index e8ab9f06..e2d98169 100644 ---- a/include/types/dns.h -+++ b/include/types/dns.h -@@ -144,7 +144,7 @@ struct dns_answer_item { - int32_t ttl; /* response TTL */ - int16_t priority; /* SRV type priority */ - uint16_t weight; /* SRV type weight */ -- int16_t port; /* SRV type port */ -+ uint16_t port; /* SRV type port */ - uint16_t data_len; /* number of bytes in target below */ - struct sockaddr address; /* IPv4 or IPv6, network format */ - char target[DNS_MAX_NAME_SIZE+1]; /* Response data: SRV or CNAME type target */ diff --git a/net/haproxy/patches/014-BUG-MEDIUM-spoe-Dont-use-the-SPOE-applet-after-releasing-it.patch b/net/haproxy/patches/014-BUG-MEDIUM-spoe-Dont-use-the-SPOE-applet-after-releasing-it.patch deleted file mode 100644 index 24a2afead9..0000000000 --- a/net/haproxy/patches/014-BUG-MEDIUM-spoe-Dont-use-the-SPOE-applet-after-releasing-it.patch +++ /dev/null @@ -1,44 +0,0 @@ -commit 89ff157c3262c8493ed48e6ac48f614791f446f8 -Author: Christopher Faulet -Date: Thu May 23 22:47:48 2019 +0200 - - BUG/MEDIUM: spoe: Don't use the SPOE applet after releasing it - - In spoe_release_appctx(), the SPOE applet may be used after it was released to - get its exit status code. Of course, HAProxy crashes when this happens. - - This patch must be backported to 1.9 and 1.8. - - (cherry picked from commit 55ae8a64e4e1175063463921375b279c31bbc6a4) - Signed-off-by: Christopher Faulet - (cherry picked from commit df29d11f522044217ea7c1373f494c2a36515b31) - Signed-off-by: Christopher Faulet - -diff --git a/src/flt_spoe.c b/src/flt_spoe.c -index 66d8b045..aeb1fde7 100644 ---- a/src/flt_spoe.c -+++ b/src/flt_spoe.c -@@ -1292,11 +1292,6 @@ spoe_release_appctx(struct appctx *appctx) - task_wakeup(ctx->strm->task, TASK_WOKEN_MSG); - } - -- /* Release allocated memory */ -- spoe_release_buffer(&spoe_appctx->buffer, -- &spoe_appctx->buffer_wait); -- pool_free(pool_head_spoe_appctx, spoe_appctx); -- - if (!LIST_ISEMPTY(&agent->rt[tid].applets)) - goto end; - -@@ -1317,6 +1312,11 @@ spoe_release_appctx(struct appctx *appctx) - } - - end: -+ /* Release allocated memory */ -+ spoe_release_buffer(&spoe_appctx->buffer, -+ &spoe_appctx->buffer_wait); -+ pool_free(pool_head_spoe_appctx, spoe_appctx); -+ - /* Update runtinme agent info */ - agent->rt[tid].frame_size = agent->max_frame_size; - list_for_each_entry(spoe_appctx, &agent->rt[tid].applets, list) diff --git a/net/haproxy/patches/015-DOC-fix-typos.patch b/net/haproxy/patches/015-DOC-fix-typos.patch deleted file mode 100644 index 813170bdaa..0000000000 --- a/net/haproxy/patches/015-DOC-fix-typos.patch +++ /dev/null @@ -1,925 +0,0 @@ -commit 5aa7b32a94ad7ac38f465f0de279f09ff6d529d3 -Author: Michael Prokop -Date: Fri May 24 10:25:45 2019 +0200 - - DOC: fix typos - - s/accidently/accidentally/ - s/any ot these messages/any of theses messages/ - s/catched/caught/ - s/completly/completely/ - s/convertor/converter/ - s/desribing/describing/ - s/developper/developer/ - s/eventhough/even though/ - s/exectution/execution/ - s/functionnality/functionality/ - s/If it receive a/If it receives a/ - s/In can even/It can even/ - s/informations/information/ - s/it will be remove /it will be removed / - s/langage/language/ - s/mentionned/mentioned/ - s/negociated/negotiated/ - s/Optionnaly/Optionally/ - s/ouputs/outputs/ - s/outweights/outweighs/ - s/ressources/resources/ - - (cherry picked from commit 4438c6061d5a2ffd5b4251027038181af9b8dc22) - [wt: removed the wurfl+da notes as well as the part on peers/server] - Signed-off-by: Willy Tarreau - (cherry picked from commit a73e4f3d7a617a51551fffd80c5dbddee81e3aaf) - [wt: removed a few other keywords like ssl_bc_alpn and show peers] - Signed-off-by: Willy Tarreau - -diff --git a/doc/DeviceAtlas-device-detection.txt b/doc/DeviceAtlas-device-detection.txt -index 4ecb44a4..144ee318 100644 ---- a/doc/DeviceAtlas-device-detection.txt -+++ b/doc/DeviceAtlas-device-detection.txt -@@ -39,7 +39,7 @@ All HTTP headers via the sample / fetch - - http-request set-header X-DeviceAtlas-Data %[da-csv-fetch(primaryHardwareType,osName,osVersion,browserName,browserVersion,browserRenderingEngine)] - --Single HTTP header (e.g. User-Agent) via the convertor -+Single HTTP header (e.g. User-Agent) via the converter - - http-request set-header X-DeviceAtlas-Data %[req.fhdr(User-Agent),da-csv-conv(primaryHardwareType,osName,osVersion,browserName,browserVersion,browserRenderingEngine)] - -diff --git a/doc/SPOE.txt b/doc/SPOE.txt -index dd36d43a..9602df95 100644 ---- a/doc/SPOE.txt -+++ b/doc/SPOE.txt -@@ -96,7 +96,7 @@ for several engines. If no name is provided, the SPOE configuration must not - contain any scope directive. - - We use a separate configuration file on purpose. By commenting SPOE filter --line, you completly disable the feature, including the parsing of sections -+line, you completely disable the feature, including the parsing of sections - reserved to SPOE. This is also a way to keep the HAProxy configuration clean. - - A SPOE configuration file must contains, at least, the SPOA configuration -@@ -272,7 +272,7 @@ option set-on-error - - * 1 a timeout occurred during the event processing. - -- * 2 an error was triggered during the ressources allocation. -+ * 2 an error was triggered during the resources allocation. - - * 3 the frame payload exceeds the frame size and it cannot be - fragmented. -@@ -923,7 +923,7 @@ For more information about known errors, see section "Errors & timeouts" - ------------------------------- - - If an error occurs, at anytime, from the agent size, a AGENT-DISCONNECT frame --is sent, with information desribing the error. such frame is also sent in reply -+is sent, with information describing the error. such frame is also sent in reply - to a HAPROXY-DISCONNECT. The agent must close the socket just after sending - this frame. - -diff --git a/doc/coding-style.txt b/doc/coding-style.txt -index 5f252ed0..9f1bd79e 100644 ---- a/doc/coding-style.txt -+++ b/doc/coding-style.txt -@@ -520,7 +520,7 @@ Wrong : - | bit = ! ! (~len++ ^ - (unsigned char) * x) ; - - Note that "sizeof" is a unary operator which is sometimes considered as a --langage keyword, but in no case it is a function. It does not require -+language keyword, but in no case it is a function. It does not require - parenthesis so it is sometimes followed by spaces and sometimes not when - there are no parenthesis. Most people do not really care as long as what - is written is unambiguous. -@@ -814,7 +814,7 @@ common to see such a thing : - This is wrong. The man page says that -1 is returned if an error occurred. It - does not suggest that any other negative value will be an error. It is possible - that a few such issues have been left in existing code. They are bugs for which --fixes are accepted, eventhough they're currently harmless since open() is not -+fixes are accepted, even though they're currently harmless since open() is not - known for returning negative values at the moment. - - -diff --git a/doc/configuration.txt b/doc/configuration.txt -index 863508f5..e044639a 100644 ---- a/doc/configuration.txt -+++ b/doc/configuration.txt -@@ -3051,7 +3051,7 @@ cookie [ rewrite | insert | prefix ] [ indirect ] [ nocache ] - - already have a cookie that would have permitted it to access this - server. When used without the "preserve" option, if the server -- emits a cookie with the same name, it will be remove before -+ emits a cookie with the same name, it will be removed before - processing. For this reason, this mode can be used to upgrade - existing configurations running in the "rewrite" mode. The cookie - will only be a session cookie and will not be stored on the -@@ -4786,7 +4786,7 @@ http-reuse { never | safe | aggressive | always } - proving that the server correctly supports connection reuse. - It should only be used when it's sure that the client can - retry a failed request once in a while and where the benefit -- of aggressive connection reuse significantly outweights the -+ of aggressive connection reuse significantly outweighs the - downsides of rare connection failures. - - - "always" : this mode is only recommended when the path to the server is -diff --git a/doc/intro.txt b/doc/intro.txt -index 7ad92db0..864fb8d6 100644 ---- a/doc/intro.txt -+++ b/doc/intro.txt -@@ -1481,7 +1481,7 @@ they are mentioned here even if not directly related to HAProxy. - - Apache is the de-facto standard HTTP server. It's a very complete and modular - project supporting both file serving and dynamic contents. It can serve as a --frontend for some application servers. In can even proxy requests and cache -+frontend for some application servers. It can even proxy requests and cache - responses. In all of these use cases, a front load balancer is commonly needed. - Apache can work in various modes, some being heavier than others. Certain - modules still require the heavier pre-forked model and will prevent Apache from -diff --git a/doc/lua.txt b/doc/lua.txt -index 7b257ad8..2e266b03 100644 ---- a/doc/lua.txt -+++ b/doc/lua.txt -@@ -412,7 +412,7 @@ The max amount of memory is configured with the option: - tune.lua.maxmem - - As many other script languages, Lua uses a garbage collector for reusing its --memory. The Lua developper can work without memory preoccupation. Usually, the -+memory. The Lua developer can work without memory preoccupation. Usually, the - garbage collector is controlled by the Lua core, but sometimes it will be useful - to run when the user/developer requires. So the garbage collector can be called - from C part or Lua part. -@@ -885,7 +885,7 @@ The task entry point - - The function "core.register_task(fcn)" executes once the function "fcn" when the - scheduler starts. This way is used for executing background task. For example, --you can use this functionnality for periodically checking the health of another -+you can use this functionality for periodically checking the health of another - service, and giving the result to each proxy needing it. - - The task is started once, if you want periodic actions, you can use the -diff --git a/doc/management.txt b/doc/management.txt -index 1b41558a..8fdea722 100644 ---- a/doc/management.txt -+++ b/doc/management.txt -@@ -1634,7 +1634,7 @@ set rate-limit ssl-sessions global - - set server / addr [port ] - Replace the current IP address of a server by the one provided. -- Optionnaly, the port can be changed using the 'port' parameter. -+ Optionally, the port can be changed using the 'port' parameter. - Note that changing the port also support switching from/to port mapping - (notation with +X or -Y), only if a port is configured for the health check. - -diff --git a/doc/netscaler-client-ip-insertion-protocol.txt b/doc/netscaler-client-ip-insertion-protocol.txt -index 559d98a8..dc64327a 100644 ---- a/doc/netscaler-client-ip-insertion-protocol.txt -+++ b/doc/netscaler-client-ip-insertion-protocol.txt -@@ -1,4 +1,4 @@ --When NetScaler application switch is used as L3+ switch, informations -+When NetScaler application switch is used as L3+ switch, information - regarding the original IP and TCP headers are lost as a new TCP - connection is created between the NetScaler and the backend server. - -diff --git a/doc/peers-v2.0.txt b/doc/peers-v2.0.txt -index a7f70dcc..02914743 100644 ---- a/doc/peers-v2.0.txt -+++ b/doc/peers-v2.0.txt -@@ -275,11 +275,11 @@ if no available remote peers are found. - - The chosen remote peer will push its all known data ending with a Resync Finished Message or a Resync Partial Message (if it it does not consider itself as full updated). - --If it receive a Resync Finished Message it will consider itself as fully updated and stops to ask for resync. -+If it receives a Resync Finished Message it will consider itself as fully updated and stops to ask for resync. - --If it receive a Resync Partial Message, the current peer will be flagged to anymore be requested and any other connected peer will be randomly chosen for a resync request (5s). -+If it receives a Resync Partial Message, the current peer will be flagged to anymore be requested and any other connected peer will be randomly chosen for a resync request (5s). - --If the session is broken before receiving any ot these messages any other connected peer will be randomly chosen for a resync request (5s). -+If the session is broken before receiving any of these messages any other connected peer will be randomly chosen for a resync request (5s). - - If the timeout expire, the process will consider itself as fully updated - -diff --git a/doc/proxy-protocol.txt b/doc/proxy-protocol.txt -index 4969180a..52d7bc71 100644 ---- a/doc/proxy-protocol.txt -+++ b/doc/proxy-protocol.txt -@@ -561,7 +561,7 @@ Contains the host name value passed by the client, as an UTF8-encoded string. - In case of TLS being used on the client connection, this is the exact copy of - the "server_name" extension as defined by RFC3546 [10], section 3.1, often - referred to as "SNI". There are probably other situations where an authority --can be mentionned on a connection without TLS being involved at all. -+can be mentioned on a connection without TLS being involved at all. - - - 2.2.3. PP2_TYPE_CRC32C -diff --git a/doc/regression-testing.txt b/doc/regression-testing.txt -new file mode 100644 -index 00000000..320c51cd ---- /dev/null -+++ b/doc/regression-testing.txt -@@ -0,0 +1,706 @@ -+ +---------------------------------------+ -+ | HAProxy regression testing with vtest | -+ +---------------------------------------+ -+ -+ -+The information found in this file are a short starting guide to help you to -+write VTC (Varnish Test Case) scripts (or VTC files) for haproxy regression testing. -+Such VTC files are currently used to test Varnish cache application developed by -+Poul-Henning Kamp. A very big thanks you to him for having helped you to add -+our haproxy C modules to vtest tool. Note that vtest was formally developed for -+varnish cache reg testing and was named varnishtest. vtest is an haproxy specific -+version of varnishtest program which reuses the non varnish cache specific code. -+ -+A lot of general information about how to write VTC files may be found in 'man/vtc.7' -+manual of varnish cache sources directory or directly on the web here: -+ -+ https://varnish-cache.org/docs/trunk/reference/vtc.html -+ -+It is *highly* recommended to read this manual before asking to haproxy ML. This -+documentation only deals with the vtest support for haproxy. -+ -+ -+vtest installation -+------------------------ -+ -+To use vtest you will have to download and compile the recent vtest -+sources found at https://github.com/vtest/VTest. -+ -+To compile vtest: -+ -+ $ cd VTest -+ $ make vtest -+ -+Note that varnishtest may be also compiled but not without the varnish cache -+sources already compiled: -+ -+ $ VARNISH_SRC=<...> make varnishtest -+ -+After having compiled these sources, the vtest executable location is at the -+root of the vtest sources directory. -+ -+ -+vtest execution -+--------------------- -+ -+vtest is able to search for the haproxy executable file it is supposed to -+launch thanks to the PATH environment variable. To force the executable to be used by -+vtest, the HAPROXY_PROGRAM environment variable for vtest may be -+typically set as follows: -+ -+ $ HAPROXY_PROGRAM=~/srcs/haproxy/haproxy vtest ... -+ -+vtest program comes with interesting options. The most interesting are: -+ -+ -t Timeout in seconds to abort the test if some launched program -+ -v By default, vtest does not dump the outputs of processus it launched -+ when the test passes. With this option the outputs are dumped even -+ when the test passes. -+ -L to always keep the temporary VTC directories. -+ -l to keep the temporary VTC directories only when the test fails. -+ -+About haproxy, when launched by vtest, -d option is enabled by default. -+ -+ -+How to write VTC files -+---------------------- -+ -+A VTC file must start with a "varnishtest" or "vtest" command line followed by a -+descriptive line enclosed by double quotes. This is not specific to the VTC files -+for haproxy. -+ -+The VTC files for haproxy must also contain a "feature ignore_unknown_macro" line -+if any macro is used for haproxy in this file. This is due to the fact that -+vtest parser code for haproxy commands generates macros the vtest -+parser code for varnish cache has no knowledge of. This line prevents vtest from -+failing in such cases. As a "cli" macro automatically generated, this -+"feature ignore_unknown_macro" is mandatory for each VTC file for haproxy. -+ -+To make vtest capable of testing haproxy, two new VTC commands have been -+implemented: "haproxy" and "syslog". "haproxy" is used to start haproxy processus. -+"syslog" is used to start syslog servers (at this time, only used by haproxy). -+ -+As haproxy cannot work without configuration file, a VTC file for haproxy must -+embed the configuration files contents for the haproxy instances it declares. -+This may be done using the following intuitive syntax construction: -conf {...}. -+Here -conf is an argument of "haproxy" VTC command to declare the configuration -+file of the haproxy instances it also declares (see "Basic HAProxy test" VTC file -+below). -+ -+As for varnish VTC files, the parser of VTC files for haproxy automatically -+generates macros for the declared frontends to be reused by the clients later -+in the script, so after having written the "haproxy" command sections. -+The syntax "fd@${my_frontend_fd_name}" must be used to bind the frontend -+listeners to localhost address and random ports (see "Environment variables" -+section of haproxy documentation). This is mandatory. -+ -+Each time the haproxy command parser finds a "fd@${xyz}" string in a 'ABC' -+"haproxy" command section, it generates three macros: 'ABC_xyz_addr', 'ABC_xyz_port' -+and 'ABC_xyz_sock', with 'ABC_xyz_sock' being resolved as 'ABC_xyz_addr -+ABC_xyz_port' typically used by clients -connect parameter. -+ -+Each haproxy instance works in their own temporary working directories located -+at '/tmp/vtc..XXXXXXXX/' (with XXXXXXXX -+a random 8 digits hexadecimal integer. This is in this temporary directory that -+the configuration file is temporarily written. -+ -+A 'stats.sock' UNIX socket is also created in this directory. There is no need -+to declare such stats sockets in the -conf {...} section. The name of the parent -+directory of the haproxy instances working directories is stored in 'tmpdir'. In -+fact this is the working directory of the current vtest processus. -+ -+There also exists 'testdir' macro which is the parent directory of the VTC file. -+It may be useful to use other files located in the same directory than the current -+VTC file. -+ -+ -+ -+VTC file examples -+----------------- -+ -+The following first VTC file is a real regression test case file for a bug which has -+been fixed by 84c844e commit. We declare a basic configuration for a 'h1' haproxy -+instance. -+ -+ varnishtest "SPOE bug: missing configuration file" -+ -+ #commit 84c844eb12b250aa86f2aadaff77c42dfc3cb619 -+ #Author: Christopher Faulet -+ #Date: Fri Mar 23 14:37:14 2018 +0100 -+ -+ # BUG/MINOR: spoe: Initialize variables used during conf parsing before any check -+ -+ # Some initializations must be done at the beginning of parse_spoe_flt to avoid -+ # segmentaion fault when first errors are caught, when the "filter spoe" line is -+ # parsed. -+ -+ haproxy h1 -conf-BAD {} { -+ defaults -+ timeout connect 5000ms -+ timeout client 50000ms -+ timeout server 50000ms -+ -+ frontend my-front -+ filter spoe -+ } -+ -+ -+-conf-BAD haproxy command argument is used. Its role it to launch haproxy with -+-c option (configuration file checking) and check that 'h1' exit(3) with 1 as -+status. Here is the output when running this VTC file: -+ -+ -+ **** top 0.0 extmacro def pwd=/home/fred/src/haproxy -+ **** top 0.0 extmacro def localhost=127.0.0.1 -+ **** top 0.0 extmacro def bad_backend=127.0.0.1 39564 -+ **** top 0.0 extmacro def bad_ip=192.0.2.255 -+ **** top 0.0 macro def testdir=//home/fred/src/varnish-cache-haproxy -+ **** top 0.0 macro def tmpdir=/tmp/vtc.6377.64329194 -+ * top 0.0 TEST /home/fred/src/varnish-cache-haproxy/spoe_bug.vtc starting -+ ** top 0.0 === varnishtest "SPOE bug: missing configuration file" -+ * top 0.0 TEST SPOE bug: missing configuration file -+ ** top 0.0 === haproxy h1 -conf-BAD {} { -+ **** h1 0.0 conf| global -+ **** h1 0.0 conf|\tstats socket /tmp/vtc.6377.64329194/h1/stats.sock level admin mode 600 -+ **** h1 0.0 conf| -+ **** h1 0.0 conf|\tdefaults -+ **** h1 0.0 conf| timeout connect 5000ms -+ **** h1 0.0 conf| timeout client 50000ms -+ **** h1 0.0 conf| timeout server 50000ms -+ **** h1 0.0 conf| -+ **** h1 0.0 conf|\tfrontend my-front -+ **** h1 0.0 conf|\t\tfilter spoe -+ **** h1 0.0 conf| -+ ** h1 0.0 haproxy_start -+ **** h1 0.0 opt_worker 0 opt_daemon 0 opt_check_mode 1 -+ **** h1 0.0 argv|exec /home/fred/src/haproxy/haproxy -c -f /tmp/vtc.6377.64329194/h1/cfg -+ **** h1 0.0 XXX 5 @277 -+ *** h1 0.0 PID: 6395 -+ **** h1 0.0 macro def h1_pid=6395 -+ **** h1 0.0 macro def h1_name=/tmp/vtc.6377.64329194/h1 -+ ** h1 0.0 Wait -+ ** h1 0.0 Stop HAproxy pid=6395 -+ **** h1 0.0 STDOUT poll 0x10 -+ ** h1 0.0 WAIT4 pid=6395 status=0x008b (user 0.000000 sys 0.000000) -+ * h1 0.0 Expected exit: 0x1 signal: 0 core: 0 -+ ---- h1 0.0 Bad exit status: 0x008b exit 0x0 signal 11 core 128 -+ * top 0.0 RESETTING after /home/fred/src/varnish-cache-haproxy/spoe_bug.vtc -+ ** h1 0.0 Reset and free h1 haproxy 6395 -+ ** h1 0.0 Wait -+ ---- h1 0.0 Assert error in haproxy_wait(), vtc_haproxy.c line 326: Condition(*(&h->fds[1]) >= 0) not true. -+ -+ * top 0.0 failure during reset -+ # top TEST /home/fred/src/varnish-cache-haproxy/spoe_bug.vtc FAILED (0.008) exit=2 -+ -+ -+'h1' exited with (128 + 11) status and a core file was produced in -+/tmp/vtc.6377.64329194/h1 directory. -+With the patch provided by 84c844e commit, varnishtest makes this VTC file pass -+as expected (verbose mode execution): -+ -+ **** top 0.0 extmacro def pwd=/home/fred/src/haproxy -+ **** top 0.0 extmacro def localhost=127.0.0.1 -+ **** top 0.0 extmacro def bad_backend=127.0.0.1 42264 -+ **** top 0.0 extmacro def bad_ip=192.0.2.255 -+ **** top 0.0 macro def testdir=//home/fred/src/varnish-cache-haproxy -+ **** top 0.0 macro def tmpdir=/tmp/vtc.25540.59b6ec5d -+ * top 0.0 TEST /home/fred/src/varnish-cache-haproxy/spoe_bug.vtc starting -+ ** top 0.0 === varnishtest "SPOE bug: missing configuration file" -+ * top 0.0 TEST SPOE bug: missing configuration file -+ ** top 0.0 === haproxy h1 -conf-BAD {} { -+ **** h1 0.0 conf| global -+ **** h1 0.0 conf|\tstats socket /tmp/vtc.25540.59b6ec5d/h1/stats.sock level admin mode 600 -+ **** h1 0.0 conf| -+ **** h1 0.0 conf|\tdefaults -+ **** h1 0.0 conf| timeout connect 5000ms -+ **** h1 0.0 conf| timeout client 50000ms -+ **** h1 0.0 conf| timeout server 50000ms -+ **** h1 0.0 conf| -+ **** h1 0.0 conf|\tfrontend my-front -+ **** h1 0.0 conf|\t\tfilter spoe -+ **** h1 0.0 conf| -+ ** h1 0.0 haproxy_start -+ **** h1 0.0 opt_worker 0 opt_daemon 0 opt_check_mode 1 -+ **** h1 0.0 argv|exec /home/fred/src/haproxy/haproxy -c -f /tmp/vtc.25540.59b6ec5d/h1/cfg -+ **** h1 0.0 XXX 5 @277 -+ *** h1 0.0 PID: 25558 -+ **** h1 0.0 macro def h1_pid=25558 -+ **** h1 0.0 macro def h1_name=/tmp/vtc.25540.59b6ec5d/h1 -+ ** h1 0.0 Wait -+ ** h1 0.0 Stop HAproxy pid=25558 -+ *** h1 0.0 debug|[ALERT] 157/135318 (25558) : parsing [/tmp/vtc.25540.59b6ec5d/h1/cfg:10] : 'filter' : ''spoe' : missing config file' -+ *** h1 0.0 debug|[ALERT] 157/135318 (25558) : Error(s) found in configuration file : /tmp/vtc.25540.59b6ec5d/h1/cfg -+ *** h1 0.0 debug|[ALERT] 157/135318 (25558) : Fatal errors found in configuration. -+ **** h1 0.0 STDOUT poll 0x10 -+ ** h1 0.0 WAIT4 pid=25558 status=0x0100 (user 0.000000 sys 0.000000) -+ ** h1 0.0 Found expected '' -+ * top 0.0 RESETTING after /home/fred/src/varnish-cache-haproxy/spoe_bug.vtc -+ ** h1 0.0 Reset and free h1 haproxy -1 -+ * top 0.0 TEST /home/fred/src/varnish-cache-haproxy/spoe_bug.vtc completed -+ # top TEST /home/fred/src/varnish-cache-haproxy/spoe_bug.vtc passed (0.004) -+ -+ -+The following VTC file does almost nothing except running a shell to list -+the contents of 'tmpdir' directory after having launched a haproxy instance -+and 's1' HTTP server. This shell also prints the content of 'cfg' 'h1' configuration -+file. -+ -+ varnishtest "List the contents of 'tmpdir'" -+ feature ignore_unknown_macro -+ -+ server s1 { -+ } -start -+ -+ haproxy h1 -conf { -+ defaults -+ mode http -+ timeout connect 5s -+ timeout server 30s -+ timeout client 30s -+ -+ backend be1 -+ server srv1 ${s1_addr}:${s1_port} -+ -+ frontend http1 -+ use_backend be1 -+ bind "fd@${my_frontend_fd}" -+ } -start -+ -+ shell { -+ echo "${tmpdir} working directory content:" -+ ls -lR ${tmpdir} -+ cat ${tmpdir}/h1/cfg -+ } -+ -+We give only the output of the shell to illustrate this example: -+ -+ . -+ . -+ . -+ ** top 0.0 === shell { -+ **** top 0.0 shell_cmd|exec 2>&1 ; -+ **** top 0.0 shell_cmd| echo "tmpdir: /tmp/vtc.32092.479d521e" -+ **** top 0.0 shell_cmd| ls -lR /tmp/vtc.32092.479d521e -+ **** top 0.0 shell_cmd| cat /tmp/vtc.32092.479d521e/h1/cfg -+ . -+ . -+ . -+ **** top 0.0 shell_out|/tmp/vtc.3808.448cbfe0 working directory content: -+ **** top 0.0 shell_out|/tmp/vtc.32092.479d521e: -+ **** top 0.0 shell_out|total 8 -+ **** top 0.0 shell_out|drwxr-xr-x 2 users 4096 Jun 7 11:09 h1 -+ **** top 0.0 shell_out|-rw-r--r-- 1 me users 84 Jun 7 11:09 INFO -+ **** top 0.0 shell_out| -+ **** top 0.0 shell_out|/tmp/vtc.32092.479d521e/h1: -+ **** top 0.0 shell_out|total 4 -+ **** top 0.0 shell_out|-rw-r----- 1 fred users 339 Jun 7 11:09 cfg -+ **** top 0.0 shell_out|srw------- 1 fred users 0 Jun 7 11:09 stats.sock -+ **** top 0.0 shell_out| global -+ **** top 0.0 shell_out|\tstats socket /tmp/vtc.32092.479d521e/h1/stats.sock level admin mode 600 -+ **** top 0.0 shell_out| -+ **** top 0.0 shell_out| defaults -+ **** top 0.0 shell_out| mode http -+ **** top 0.0 shell_out| timeout connect 5s -+ **** top 0.0 shell_out| timeout server 30s -+ **** top 0.0 shell_out| timeout client 30s -+ **** top 0.0 shell_out| -+ **** top 0.0 shell_out| backend be1 -+ **** top 0.0 shell_out| server srv1 127.0.0.1:36984 -+ **** top 0.0 shell_out| -+ **** top 0.0 shell_out| frontend http1 -+ **** top 0.0 shell_out| use_backend be1 -+ **** top 0.0 shell_out| bind "fd@${my_frontend_fd}" -+ **** top 0.0 shell_status = 0x0000 -+ -+ -+The following example illustrate how to run a basic HTTP transaction between 'c1' -+client and 's1' server with 'http1' as haproxy frontend. This frontend listen -+on TCP socket with 'my_frontend_fd' as file descriptor. -+ -+ # Mandatory line -+ varnishtest "Basic HAproxy test" -+ -+ # As some macros for haproxy are used in this file, this line is mandatory. -+ feature ignore_unknown_macro -+ -+ server s1 { -+ rxreq -+ txresp -body "s1 >>> Hello world!" -+ } -start -+ -+ haproxy h1 -conf { -+ # Configuration file of 'h1' haproxy instance. -+ defaults -+ mode http -+ timeout connect 5s -+ timeout server 30s -+ timeout client 30s -+ -+ backend be1 -+ # declare 'srv1' server to point to 's1' server instance declare above. -+ server srv1 ${s1_addr}:${s1_port} -+ -+ frontend http1 -+ use_backend be1 -+ bind "fd@${my_frontend_fd}" -+ } -start -+ -+ client c1 -connect ${h1_my_frontend_fd_sock} { -+ txreq -url "/" -+ rxresp -+ expect resp.status == 200 -+ expect resp.body == "s1 >>> Hello world!" -+ } -run -+ -+ -+It is possible to shorten the previous VTC file haproxy command section as follows: -+ -+ haproxy h1 -conf { -+ # Configuration file of 'h1' haproxy instance. -+ defaults -+ mode http -+ timeout connect 5s -+ timeout server 30s -+ timeout client 30s -+ } -+ -+In this latter example, "backend" and "frontend" sections are automatically -+generated depending on the declarations of server instances. -+ -+ -+Another interesting real regression test case is the following: we declare one -+server 's1', a syslog server 'Slg_1' and a basic haproxy configuration for 'h1' -+haproxy instance. Here we want to check that the syslog message are correctly -+formatted thanks to "expect" "syslog" command (see syslog Slg_1 {...} command) -+below. -+ -+ varnishtest "Wrong ip/port logging" -+ feature ignore_unknown_macro -+ -+ #commit d02286d6c866e5c0a7eb6fbb127fa57f3becaf16 -+ #Author: Willy Tarreau -+ #Date: Fri Jun 23 11:23:43 2017 +0200 -+ # -+ # BUG/MINOR: log: pin the front connection when front ip/ports are logged -+ # -+ # Mathias Weiersmueller reported an interesting issue with logs which Lukas -+ # diagnosed as dating back from commit 9b061e332 (1.5-dev9). When front -+ # connection information (ip, port) are logged in TCP mode and the log is -+ # emitted at the end of the connection (eg: because %B or any log tag -+ # requiring LW_BYTES is set), the log is emitted after the connection is -+ # closed, so the address and ports cannot be retrieved anymore. -+ # -+ # It could be argued that we'd make a special case of these to immediately -+ # retrieve the source and destination addresses from the connection, but it -+ # seems cleaner to simply pin the front connection, marking it "tracked" by -+ # adding the LW_XPRT flag to mention that we'll need some of these elements -+ # at the last moment. Only LW_FRTIP and LW_CLIP are affected. Note that after -+ # this change, LW_FRTIP could simply be removed as it's not used anywhere. -+ -+ # Note that the problem doesn't happen when using %[src] or %[dst] since -+ # all sample expressions set LW_XPRT. -+ -+ -+ server s1 { -+ rxreq -+ txresp -+ } -start -+ -+ syslog Slg_1 -level notice { -+ recv -+ recv -+ recv info -+ expect ~ \"dip\":\"${h1_fe_1_addr}\",\"dport\":\"${h1_fe_1_port}.*\"ts\":\"cD\",\" -+ } -start -+ -+ haproxy h1 -conf { -+ global -+ log ${Slg_1_addr}:${Slg_1_port} local0 -+ -+ defaults -+ log global -+ timeout connect 3000 -+ timeout client 5 -+ timeout server 10000 -+ -+ frontend fe1 -+ bind "fd@${fe_1}" -+ mode tcp -+ log-format {\"dip\":\"%fi\",\"dport\":\"%fp\",\"c_ip\":\"%ci\",\"c_port\":\"%cp\",\"fe_name\":\"%ft\",\"be_name\":\"%b\",\"s_name\":\"%s\",\"ts\":\"%ts\",\"bytes_read\":\"%B\"} -+ default_backend be_app -+ -+ backend be_app -+ server app1 ${s1_addr}:${s1_port} check -+ } -start -+ -+ client c1 -connect ${h1_fe_1_sock} { -+ txreq -url "/" -+ delay 0.02 -+ } -run -+ -+ syslog Slg_1 -wait -+ -+ -+Here is the output produced by varnishtest with the latter VTC file: -+ -+ **** top 0.0 extmacro def pwd=/home/fred/src/haproxy -+ **** top 0.0 extmacro def localhost=127.0.0.1 -+ **** top 0.0 extmacro def bad_backend=127.0.0.1 40386 -+ **** top 0.0 extmacro def bad_ip=192.0.2.255 -+ **** top 0.0 macro def testdir=//home/fred/src/varnish-cache-haproxy -+ **** top 0.0 macro def tmpdir=/tmp/vtc.15752.560ca66b -+ * top 0.0 TEST /home/fred/src/varnish-cache-haproxy/d02286d.vtc starting -+ ** top 0.0 === varnishtest "HAPEE bug 2788" -+ * top 0.0 TEST HAPEE bug 2788 -+ ** top 0.0 === feature ignore_unknown_macro -+ ** top 0.0 === server s1 { -+ ** s1 0.0 Starting server -+ **** s1 0.0 macro def s1_addr=127.0.0.1 -+ **** s1 0.0 macro def s1_port=35564 -+ **** s1 0.0 macro def s1_sock=127.0.0.1 35564 -+ * s1 0.0 Listen on 127.0.0.1 35564 -+ ** top 0.0 === syslog Slg_1 -level notice { -+ ** Slg_1 0.0 Starting syslog server -+ ** s1 0.0 Started on 127.0.0.1 35564 -+ **** Slg_1 0.0 macro def Slg_1_addr=127.0.0.1 -+ **** Slg_1 0.0 macro def Slg_1_port=33012 -+ **** Slg_1 0.0 macro def Slg_1_sock=127.0.0.1 33012 -+ * Slg_1 0.0 Bound on 127.0.0.1 33012 -+ ** top 0.0 === haproxy h1 -conf { -+ ** Slg_1 0.0 Started on 127.0.0.1 33012 (level: 5) -+ ** Slg_1 0.0 === recv -+ **** h1 0.0 macro def h1_fe_1_sock=::1 51782 -+ **** h1 0.0 macro def h1_fe_1_addr=::1 -+ **** h1 0.0 macro def h1_fe_1_port=51782 -+ **** h1 0.0 setenv(fe_1, 7) -+ **** h1 0.0 conf| global -+ **** h1 0.0 conf|\tstats socket /tmp/vtc.15752.560ca66b/h1/stats.sock level admin mode 600 -+ **** h1 0.0 conf| -+ **** h1 0.0 conf| global -+ **** h1 0.0 conf| log 127.0.0.1:33012 local0 -+ **** h1 0.0 conf| -+ **** h1 0.0 conf| defaults -+ **** h1 0.0 conf| log global -+ **** h1 0.0 conf| timeout connect 3000 -+ **** h1 0.0 conf| timeout client 5 -+ **** h1 0.0 conf| timeout server 10000 -+ **** h1 0.0 conf| -+ **** h1 0.0 conf| frontend fe1 -+ **** h1 0.0 conf| bind "fd@${fe_1}" -+ **** h1 0.0 conf| mode tcp -+ **** h1 0.0 conf| log-format {\"dip\":\"%fi\",\"dport\":\"%fp\",\"c_ip\":\"%ci\",\"c_port\":\"%cp\",\"fe_name\":\"%ft\",\"be_name\":\"%b\",\"s_name\":\"%s\",\"ts\":\"%ts\",\"bytes_read\":\"%B\"} -+ **** h1 0.0 conf| default_backend be_app -+ **** h1 0.0 conf| -+ **** h1 0.0 conf| backend be_app -+ **** h1 0.0 conf| server app1 127.0.0.1:35564 check -+ ** h1 0.0 haproxy_start -+ **** h1 0.0 opt_worker 0 opt_daemon 0 opt_check_mode 0 -+ **** h1 0.0 argv|exec /home/fred/src/haproxy/haproxy -d -f /tmp/vtc.15752.560ca66b/h1/cfg -+ **** h1 0.0 XXX 9 @277 -+ *** h1 0.0 PID: 15787 -+ **** h1 0.0 macro def h1_pid=15787 -+ **** h1 0.0 macro def h1_name=/tmp/vtc.15752.560ca66b/h1 -+ ** top 0.0 === client c1 -connect ${h1_fe_1_sock} { -+ ** c1 0.0 Starting client -+ ** c1 0.0 Waiting for client -+ *** c1 0.0 Connect to ::1 51782 -+ *** c1 0.0 connected fd 8 from ::1 46962 to ::1 51782 -+ ** c1 0.0 === txreq -url "/" -+ **** c1 0.0 txreq|GET / HTTP/1.1\r -+ **** c1 0.0 txreq|Host: 127.0.0.1\r -+ **** c1 0.0 txreq|\r -+ ** c1 0.0 === delay 0.02 -+ *** c1 0.0 delaying 0.02 second(s) -+ *** h1 0.0 debug|Note: setting global.maxconn to 2000. -+ *** h1 0.0 debug|Available polling systems : -+ *** h1 0.0 debug| epoll : -+ *** h1 0.0 debug|pref=300, -+ *** h1 0.0 debug| test result OK -+ *** h1 0.0 debug| poll : pref=200, test result OK -+ *** h1 0.0 debug| select : -+ *** h1 0.0 debug|pref=150, test result FAILED -+ *** h1 0.0 debug|Total: 3 (2 usable), will use epoll. -+ *** h1 0.0 debug| -+ *** h1 0.0 debug|Available filters : -+ *** h1 0.0 debug|\t[SPOE] spoe -+ *** h1 0.0 debug|\t[COMP] compression -+ *** h1 0.0 debug|\t[TRACE] trace -+ **** Slg_1 0.0 syslog|<133>Jun 7 14:12:51 haproxy[15787]: Proxy fe1 started. -+ ** Slg_1 0.0 === recv -+ **** Slg_1 0.0 syslog|<133>Jun 7 14:12:51 haproxy[15787]: Proxy be_app started. -+ ** Slg_1 0.0 === recv info -+ *** h1 0.0 debug|00000000:fe1.accept(0007)=000a from [::1:46962] -+ *** s1 0.0 accepted fd 6 127.0.0.1 56770 -+ ** s1 0.0 === rxreq -+ **** s1 0.0 rxhdr|GET / HTTP/1.1\r -+ **** s1 0.0 rxhdr|Host: 127.0.0.1\r -+ **** s1 0.0 rxhdr|\r -+ **** s1 0.0 rxhdrlen = 35 -+ **** s1 0.0 http[ 0] |GET -+ **** s1 0.0 http[ 1] |/ -+ **** s1 0.0 http[ 2] |HTTP/1.1 -+ **** s1 0.0 http[ 3] |Host: 127.0.0.1 -+ **** s1 0.0 bodylen = 0 -+ ** s1 0.0 === txresp -+ **** s1 0.0 txresp|HTTP/1.1 200 OK\r -+ **** s1 0.0 txresp|Content-Length: 0\r -+ **** s1 0.0 txresp|\r -+ *** s1 0.0 shutting fd 6 -+ ** s1 0.0 Ending -+ *** h1 0.0 debug|00000000:be_app.srvcls[000a:000c] -+ *** h1 0.0 debug|00000000:be_app.clicls[000a:000c] -+ *** h1 0.0 debug|00000000:be_app.closed[000a:000c] -+ **** Slg_1 0.0 syslog|<134>Jun 7 14:12:51 haproxy[15787]: {"dip":"","dport":"0","c_ip":"::1","c_port":"46962","fe_name":"fe1","be_name":"be_app","s_name":"app1","ts":"cD","bytes_read":"38"} -+ ** Slg_1 0.0 === expect ~ \"dip\":\"${h1_fe_1_addr}\",\"dport\":\"${h1_fe_1_p... -+ ---- Slg_1 0.0 EXPECT FAILED ~ "\"dip\":\"::1\",\"dport\":\"51782.*\"ts\":\"cD\",\"" -+ *** c1 0.0 closing fd 8 -+ ** c1 0.0 Ending -+ * top 0.0 RESETTING after /home/fred/src/varnish-cache-haproxy/d02286d.vtc -+ ** h1 0.0 Reset and free h1 haproxy 15787 -+ ** h1 0.0 Wait -+ ** h1 0.0 Stop HAproxy pid=15787 -+ **** h1 0.0 Kill(2)=0: Success -+ **** h1 0.0 STDOUT poll 0x10 -+ ** h1 0.1 WAIT4 pid=15787 status=0x0002 (user 0.000000 sys 0.004000) -+ ** s1 0.1 Waiting for server (4/-1) -+ ** Slg_1 0.1 Waiting for syslog server (5) -+ * top 0.1 TEST /home/fred/src/varnish-cache-haproxy/d02286d.vtc FAILED -+ # top TEST /home/fred/src/varnish-cache-haproxy/d02286d.vtc FAILED (0.131) exit=2 -+ -+This test does not pass without the bug fix of d02286d commit. Indeed the third syslog -+message received by 'Slg_1' syslog server does not match the regular expression -+of the "syslog" "expect" command: -+ -+ expect ~ \"dip\":\"${h1_fe_1_addr}\",\"dport\":\"${h1_fe_1_port}.*\"ts\":\"cD\",\" -+ -+(the IP address and port are missing), contrary to what happens with the correct bug fix: -+ -+ **** top 0.0 extmacro def pwd=/home/fred/src/haproxy -+ **** top 0.0 extmacro def localhost=127.0.0.1 -+ **** top 0.0 extmacro def bad_backend=127.0.0.1 37284 -+ **** top 0.0 extmacro def bad_ip=192.0.2.255 -+ **** top 0.0 macro def testdir=//home/fred/src/varnish-cache-haproxy -+ **** top 0.0 macro def tmpdir=/tmp/vtc.12696.186b28b0 -+ * top 0.0 TEST /home/fred/src/varnish-cache-haproxy/d02286d.vtc starting -+ ** top 0.0 === varnishtest "HAPEE bug 2788" -+ * top 0.0 TEST HAPEE bug 2788 -+ ** top 0.0 === feature ignore_unknown_macro -+ ** top 0.0 === server s1 { -+ ** s1 0.0 Starting server -+ **** s1 0.0 macro def s1_addr=127.0.0.1 -+ **** s1 0.0 macro def s1_port=53384 -+ **** s1 0.0 macro def s1_sock=127.0.0.1 53384 -+ * s1 0.0 Listen on 127.0.0.1 53384 -+ ** top 0.0 === syslog Slg_1 -level notice { -+ ** Slg_1 0.0 Starting syslog server -+ **** Slg_1 0.0 macro def Slg_1_addr=127.0.0.1 -+ ** s1 0.0 Started on 127.0.0.1 53384 -+ **** Slg_1 0.0 macro def Slg_1_port=36195 -+ **** Slg_1 0.0 macro def Slg_1_sock=127.0.0.1 36195 -+ * Slg_1 0.0 Bound on 127.0.0.1 36195 -+ ** top 0.0 === haproxy h1 -conf { -+ ** Slg_1 0.0 Started on 127.0.0.1 36195 (level: 5) -+ ** Slg_1 0.0 === recv -+ **** h1 0.0 macro def h1_fe_1_sock=::1 39264 -+ **** h1 0.0 macro def h1_fe_1_addr=::1 -+ **** h1 0.0 macro def h1_fe_1_port=39264 -+ **** h1 0.0 setenv(fe_1, 7) -+ **** h1 0.0 conf| global -+ **** h1 0.0 conf|\tstats socket /tmp/vtc.12696.186b28b0/h1/stats.sock level admin mode 600 -+ **** h1 0.0 conf| -+ **** h1 0.0 conf| global -+ **** h1 0.0 conf| log 127.0.0.1:36195 local0 -+ **** h1 0.0 conf| -+ **** h1 0.0 conf| defaults -+ **** h1 0.0 conf| log global -+ **** h1 0.0 conf| timeout connect 3000 -+ **** h1 0.0 conf| timeout client 5 -+ **** h1 0.0 conf| timeout server 10000 -+ **** h1 0.0 conf| -+ **** h1 0.0 conf| frontend fe1 -+ **** h1 0.0 conf| bind "fd@${fe_1}" -+ **** h1 0.0 conf| mode tcp -+ **** h1 0.0 conf| log-format {\"dip\":\"%fi\",\"dport\":\"%fp\",\"c_ip\":\"%ci\",\"c_port\":\"%cp\",\"fe_name\":\"%ft\",\"be_name\":\"%b\",\"s_name\":\"%s\",\"ts\":\"%ts\",\"bytes_read\":\"%B\"} -+ **** h1 0.0 conf| default_backend be_app -+ **** h1 0.0 conf| -+ **** h1 0.0 conf| backend be_app -+ **** h1 0.0 conf| server app1 127.0.0.1:53384 check -+ ** h1 0.0 haproxy_start -+ **** h1 0.0 opt_worker 0 opt_daemon 0 opt_check_mode 0 -+ **** h1 0.0 argv|exec /home/fred/src/haproxy/haproxy -d -f /tmp/vtc.12696.186b28b0/h1/cfg -+ **** h1 0.0 XXX 9 @277 -+ *** h1 0.0 PID: 12728 -+ **** h1 0.0 macro def h1_pid=12728 -+ **** h1 0.0 macro def h1_name=/tmp/vtc.12696.186b28b0/h1 -+ ** top 0.0 === client c1 -connect ${h1_fe_1_sock} { -+ ** c1 0.0 Starting client -+ ** c1 0.0 Waiting for client -+ *** c1 0.0 Connect to ::1 39264 -+ *** c1 0.0 connected fd 8 from ::1 41245 to ::1 39264 -+ ** c1 0.0 === txreq -url "/" -+ **** c1 0.0 txreq|GET / HTTP/1.1\r -+ **** c1 0.0 txreq|Host: 127.0.0.1\r -+ **** c1 0.0 txreq|\r -+ ** c1 0.0 === delay 0.02 -+ *** c1 0.0 delaying 0.02 second(s) -+ *** h1 0.0 debug|Note: setting global.maxconn to 2000. -+ *** h1 0.0 debug|Available polling systems : -+ *** h1 0.0 debug| epoll : pref=300, -+ *** h1 0.0 debug| test result OK -+ *** h1 0.0 debug| poll : pref=200, test result OK -+ *** h1 0.0 debug| select : pref=150, test result FAILED -+ *** h1 0.0 debug|Total: 3 (2 usable), will use epoll. -+ *** h1 0.0 debug| -+ *** h1 0.0 debug|Available filters : -+ *** h1 0.0 debug|\t[SPOE] spoe -+ *** h1 0.0 debug|\t[COMP] compression -+ *** h1 0.0 debug|\t[TRACE] trace -+ *** h1 0.0 debug|Using epoll() as the polling mechanism. -+ **** Slg_1 0.0 syslog|<133>Jun 7 14:10:18 haproxy[12728]: Proxy fe1 started. -+ ** Slg_1 0.0 === recv -+ **** Slg_1 0.0 syslog|<133>Jun 7 14:10:18 haproxy[12728]: Proxy be_app started. -+ ** Slg_1 0.0 === recv info -+ *** h1 0.0 debug|00000000:fe1.accept(0007)=000c from [::1:41245] ALPN= -+ *** s1 0.0 accepted fd 6 127.0.0.1 49946 -+ ** s1 0.0 === rxreq -+ **** s1 0.0 rxhdr|GET / HTTP/1.1\r -+ **** s1 0.0 rxhdr|Host: 127.0.0.1\r -+ **** s1 0.0 rxhdr|\r -+ **** s1 0.0 rxhdrlen = 35 -+ **** s1 0.0 http[ 0] |GET -+ **** s1 0.0 http[ 1] |/ -+ **** s1 0.0 http[ 2] |HTTP/1.1 -+ **** s1 0.0 http[ 3] |Host: 127.0.0.1 -+ **** s1 0.0 bodylen = 0 -+ ** s1 0.0 === txresp -+ **** s1 0.0 txresp|HTTP/1.1 200 OK\r -+ **** s1 0.0 txresp|Content-Length: 0\r -+ **** s1 0.0 txresp|\r -+ *** s1 0.0 shutting fd 6 -+ ** s1 0.0 Ending -+ *** h1 0.0 debug|00000000:be_app.srvcls[000c:adfd] -+ *** h1 0.0 debug|00000000:be_app.clicls[000c:adfd] -+ *** h1 0.0 debug|00000000:be_app.closed[000c:adfd] -+ **** Slg_1 0.0 syslog|<134>Jun 7 14:10:18 haproxy[12728]: {"dip":"::1","dport":"39264","c_ip":"::1","c_port":"41245","fe_name":"fe1","be_name":"be_app","s_name":"app1","ts":"cD","bytes_read":"38"} -+ ** Slg_1 0.0 === expect ~ \"dip\":\"${h1_fe_1_addr}\",\"dport\":\"${h1_fe_1_p... -+ **** Slg_1 0.0 EXPECT MATCH ~ "\"dip\":\"::1\",\"dport\":\"39264.*\"ts\":\"cD\",\"" -+ *** Slg_1 0.0 shutting fd 5 -+ ** Slg_1 0.0 Ending -+ *** c1 0.0 closing fd 8 -+ ** c1 0.0 Ending -+ ** top 0.0 === syslog Slg_1 -wait -+ ** Slg_1 0.0 Waiting for syslog server (-1) -+ * top 0.0 RESETTING after /home/fred/src/varnish-cache-haproxy/d02286d.vtc -+ ** h1 0.0 Reset and free h1 haproxy 12728 -+ ** h1 0.0 Wait -+ ** h1 0.0 Stop HAproxy pid=12728 -+ **** h1 0.0 Kill(2)=0: Success -+ **** h1 0.0 STDOUT poll 0x10 -+ ** h1 0.1 WAIT4 pid=12728 status=0x0002 (user 0.000000 sys 0.004000) -+ ** s1 0.1 Waiting for server (4/-1) -+ * top 0.1 TEST /home/fred/src/varnish-cache-haproxy/d02286d.vtc completed -+ # top TEST /home/fred/src/varnish-cache-haproxy/d02286d.vtc passed (0.128) -+ -+In this latter execution the third syslog message is correct: -+ -+ **** Slg_1 0.0 syslog|<134>Jun 7 14:10:18 haproxy[12728]: {"dip":"::1","dport":"39264","c_ip":"::1","c_port":"41245","fe_name":"fe1","be_name":"be_app","s_name":"app1","ts":"cD","bytes_read":"38"} diff --git a/net/haproxy/patches/016-BUG-MINOR-ssl_sock-Fix-memory-leak-when-disabling-compression.patch b/net/haproxy/patches/016-BUG-MINOR-ssl_sock-Fix-memory-leak-when-disabling-compression.patch deleted file mode 100644 index dc989f1f8e..0000000000 --- a/net/haproxy/patches/016-BUG-MINOR-ssl_sock-Fix-memory-leak-when-disabling-compression.patch +++ /dev/null @@ -1,53 +0,0 @@ -commit b3dae591a4fb47922d4235cf05ac66bcce443cf4 -Author: Ilya Shipitsin -Date: Sat May 25 03:38:14 2019 +0500 - - BUG/MINOR: ssl_sock: Fix memory leak when disabling compression - - according to manpage: - - sk_TYPE_zero() sets the number of elements in sk to zero. It - does not free sk so after this call sk is still valid. - - so we need to free all elements - - [wt: seems like it has been there forever and should be backported - to all stable branches] - - (cherry picked from commit e242f3dfb8ae2f27de9d10d90a783df05d5c849b) - [wt: adjusted context due to libressl detection] - Signed-off-by: Willy Tarreau - (cherry picked from commit 273c61dfb45d968eb8b677616130cda6586977f0) - [wt: minor adjustments due to version detection and local variables] - Signed-off-by: Willy Tarreau - -diff --git a/src/ssl_sock.c b/src/ssl_sock.c -index fbb7cf2b..3ab63342 100644 ---- a/src/ssl_sock.c -+++ b/src/ssl_sock.c -@@ -8959,11 +8959,10 @@ static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA * - __attribute__((constructor)) - static void __ssl_sock_init(void) - { -+ STACK_OF(SSL_COMP)* cm; - char *ptr; - int i; - -- STACK_OF(SSL_COMP)* cm; -- - if (global_ssl.listen_default_ciphers) - global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers); - if (global_ssl.connect_default_ciphers) -@@ -8978,7 +8977,11 @@ static void __ssl_sock_init(void) - xprt_register(XPRT_SSL, &ssl_sock); - SSL_library_init(); - cm = SSL_COMP_get_compression_methods(); -- sk_SSL_COMP_zero(cm); -+ i = sk_SSL_COMP_num(cm); -+ while (i--) { -+ (void) sk_SSL_COMP_pop(cm); -+ } -+ - #ifdef USE_THREAD - ssl_locking_init(); - #endif diff --git a/net/haproxy/patches/017-BUILD-ssl-fix-latest-LibreSSL-reg-test-error.patch b/net/haproxy/patches/017-BUILD-ssl-fix-latest-LibreSSL-reg-test-error.patch deleted file mode 100644 index aa8bd61364..0000000000 --- a/net/haproxy/patches/017-BUILD-ssl-fix-latest-LibreSSL-reg-test-error.patch +++ /dev/null @@ -1,46 +0,0 @@ -commit e834ca5c6914c71a86138362423b9d6e7ce15a78 -Author: Ilya Shipitsin -Date: Sat May 25 19:30:50 2019 +0500 - - BUILD: ssl: fix latest LibreSSL reg-test error - - starting with OpenSSL 1.0.0 recommended way to disable compression is - using SSL_OP_NO_COMPRESSION when creating context. - - manipulations with SSL_COMP_get_compression_methods, sk_SSL_COMP_num - are only required for OpenSSL < 1.0.0 - - (cherry picked from commit 0590f44254da9203a3c9d239836f4703aa6d543b) - Signed-off-by: Willy Tarreau - (cherry picked from commit be086d6dc7029aec9349e54ab5cccc499892bd61) - [wt: context adjustments] - Signed-off-by: Willy Tarreau - -diff --git a/src/ssl_sock.c b/src/ssl_sock.c -index 3ab63342..3436459f 100644 ---- a/src/ssl_sock.c -+++ b/src/ssl_sock.c -@@ -8959,7 +8959,9 @@ static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA * - __attribute__((constructor)) - static void __ssl_sock_init(void) - { -+#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION)) - STACK_OF(SSL_COMP)* cm; -+#endif - char *ptr; - int i; - -@@ -8976,11 +8978,13 @@ static void __ssl_sock_init(void) - - xprt_register(XPRT_SSL, &ssl_sock); - SSL_library_init(); -+#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION)) - cm = SSL_COMP_get_compression_methods(); - i = sk_SSL_COMP_num(cm); - while (i--) { - (void) sk_SSL_COMP_pop(cm); - } -+#endif - - #ifdef USE_THREAD - ssl_locking_init(); diff --git a/net/haproxy/patches/018-BUG-MAJOR-lb-threads-make-sure-the-avoided-server-is-not-full-on-second-pass.patch b/net/haproxy/patches/018-BUG-MAJOR-lb-threads-make-sure-the-avoided-server-is-not-full-on-second-pass.patch deleted file mode 100644 index 0fc5fb1636..0000000000 --- a/net/haproxy/patches/018-BUG-MAJOR-lb-threads-make-sure-the-avoided-server-is-not-full-on-second-pass.patch +++ /dev/null @@ -1,54 +0,0 @@ -commit 5d60902ec7883bb05927c648638a009eb930acc7 -Author: Willy Tarreau -Date: Mon May 27 10:17:05 2019 +0200 - - BUG/MAJOR: lb/threads: make sure the avoided server is not full on second pass - - In fwrr_get_next_server(), we optionally pass a server to avoid. It - usually points to the current server during a redispatch operation. If - this server is usable, an "avoided" pointer is set and we continue to - look for another server. If in the end no other server is found, then - we fall back to this avoided one, which is still better than nothing. - - The problem that may arise with threads is that in the mean time, this - avoided server might have received extra connections and might not be - usable anymore. This causes it to be queued a second time in the "full" - list and the loop to search for a server again, ending up on this one - again and so on. - - This patch makes sure that we break out of the loop when we have to - pick the avoided server. It's probably what the code intended to do - as the current break statement causes fwrr_update_position() and - fwrr_dequeue_srv() to be called again on the avoided server. - - It must be backported to 1.9 and 1.8, and seems appropriate for older - versions though it's unclear what the impact of this bug might be - there since the race doesn't exist and we're left with the double - update of the server's position. - - (cherry picked from commit b6195ef2a6b0cb3f68bc34735313daa640ab3e92) - Signed-off-by: Willy Tarreau - (cherry picked from commit 7df15f275af90110e6ab4ec75065cbfabdf764ec) - Signed-off-by: Willy Tarreau - -diff --git a/src/lb_fwrr.c b/src/lb_fwrr.c -index cba7db5f..33181b46 100644 ---- a/src/lb_fwrr.c -+++ b/src/lb_fwrr.c -@@ -504,7 +504,7 @@ struct server *fwrr_get_next_server(struct proxy *p, struct server *srvtoavoid) - if (switched) { - if (avoided) { - srv = avoided; -- break; -+ goto take_this_one; - } - goto requeue_servers; - } -@@ -534,6 +534,7 @@ struct server *fwrr_get_next_server(struct proxy *p, struct server *srvtoavoid) - full = srv; - } - -+ take_this_one: - /* OK, we got the best server, let's update it */ - fwrr_queue_srv(srv); - diff --git a/net/haproxy/patches/019-BUG-MEDIUM-http-fix-http-request-reject-when-not-final.patch b/net/haproxy/patches/019-BUG-MEDIUM-http-fix-http-request-reject-when-not-final.patch deleted file mode 100644 index 6f008d8a83..0000000000 --- a/net/haproxy/patches/019-BUG-MEDIUM-http-fix-http-request-reject-when-not-final.patch +++ /dev/null @@ -1,43 +0,0 @@ -commit 339e69400f87c34e28c67eaab6e503dc41b29d48 -Author: Willy Tarreau -Date: Tue May 28 08:26:17 2019 +0200 - - BUG/MEDIUM: http: fix "http-request reject" when not final - - When "http-request reject" was introduced in 1.8 with commit 53275e8b0 - ("MINOR: http: implement the "http-request reject" rule"), it was already - broken. The code mentions "it always returns ACT_RET_STOP" and obviously - a gross copy-paste made it ACT_RET_CONT. If the rule is the last one it - properly blocks, but if not the last one it gets ignored, as can be seen - with this simple configuration : - - frontend f1 - bind :8011 - mode http - http-request reject - http-request redirect location / - - This trivial fix must be backported to 1.9 and 1.8. It is tracked by - github issue #107. - - (cherry picked from commit 11c90fbd92cfaa5695e328481402d62d536456ef) - Signed-off-by: Willy Tarreau - (cherry picked from commit f6d5f2b27634cf3f8591016985b9fb81a1caf01c) - Signed-off-by: Christopher Faulet - - [Cf: The fix was applied in the file src/proto_http.c because, in 1.8, the file - src/http_act.c does not exist.] - -diff --git a/src/proto_http.c b/src/proto_http.c -index 32aeef2d..e5792f8c 100644 ---- a/src/proto_http.c -+++ b/src/proto_http.c -@@ -12157,7 +12157,7 @@ enum act_return http_action_reject(struct act_rule *rule, struct proxy *px, - if (!(s->flags & SF_FINST_MASK)) - s->flags |= SF_FINST_R; - -- return ACT_RET_CONT; -+ return ACT_RET_STOP; - } - - /* parse the "reject" action: diff --git a/net/haproxy/patches/020-BUG-MINOR-deinit-threads-make-hard-stop-after-perform-a-clean-exit.patch b/net/haproxy/patches/020-BUG-MINOR-deinit-threads-make-hard-stop-after-perform-a-clean-exit.patch deleted file mode 100644 index fd4c549028..0000000000 --- a/net/haproxy/patches/020-BUG-MINOR-deinit-threads-make-hard-stop-after-perform-a-clean-exit.patch +++ /dev/null @@ -1,71 +0,0 @@ -commit ee60daed3071426242fcacbb1cd9603a825b359e -Author: Willy Tarreau -Date: Sun Jun 2 11:11:29 2019 +0200 - - BUG/MINOR: deinit/threads: make hard-stop-after perform a clean exit - - As reported in GH issue #99, when hard-stop-after triggers and threads - are in use, the chance that any thread releases the resources in use by - the other ones is non-null. Thus no thread should be allowed to deinit() - nor exit by itself. - - Here we take a different approach. We simply use a 3rd possible value - for the "killed" variable so that all threads know they must break out - of the run-poll-loop and immediately stop. - - This patch was tested by commenting the stream_shutdown() calls in - hard_stop() to increase the chances to see a stream use released - resources. With this fix applied, it never crashes anymore. - - This fix should be backported to 1.9 and 1.8. - - (cherry picked from commit 7067b3a92efc9c9a7c3239245fdc96ea7310f46a) - Signed-off-by: Willy Tarreau - (cherry picked from commit daf91d3a5c8d2b47878580a0e0bde654d92ad42a) - Signed-off-by: Christopher Faulet - -diff --git a/include/types/global.h b/include/types/global.h -index bd7761cd..d3721d03 100644 ---- a/include/types/global.h -+++ b/include/types/global.h -@@ -213,7 +213,7 @@ extern const int zero; - extern const int one; - extern const struct linger nolinger; - extern int stopping; /* non zero means stopping in progress */ --extern int killed; /* non zero means a hard-stop is triggered */ -+extern int killed; /* >0 means a hard-stop is triggered, >1 means hard-stop immediately */ - extern char hostname[MAX_HOSTNAME_LEN]; - extern char localpeer[MAX_HOSTNAME_LEN]; - extern struct list global_listener_queue; /* list of the temporarily limited listeners */ -diff --git a/src/haproxy.c b/src/haproxy.c -index 105cde6f..6ea17a0c 100644 ---- a/src/haproxy.c -+++ b/src/haproxy.c -@@ -2431,6 +2431,10 @@ static void run_poll_loop() - if (tid == 0 && jobs == 0) - THREAD_WANT_SYNC(); - -+ /* also stop if we failed to cleanly stop all tasks */ -+ if (killed > 1) -+ break; -+ - /* expire immediately if events are pending */ - exp = now_ms; - if (fd_cache_mask & tid_bit) -diff --git a/src/proxy.c b/src/proxy.c -index cff6c0aa..ef491aed 100644 ---- a/src/proxy.c -+++ b/src/proxy.c -@@ -942,9 +942,9 @@ struct task *hard_stop(struct task *t) - if (killed) { - ha_warning("Some tasks resisted to hard-stop, exiting now.\n"); - send_log(NULL, LOG_WARNING, "Some tasks resisted to hard-stop, exiting now.\n"); -- /* Do some cleanup and explicitely quit */ -- deinit(); -- exit(0); -+ killed = 2; -+ t->expire = TICK_ETERNITY; -+ return t; - } - - ha_warning("soft-stop running for too long, performing a hard-stop.\n"); diff --git a/net/haproxy/patches/021-BUG-MEDIUM-connection-fix-multiple-handshake-polling-issues.patch b/net/haproxy/patches/021-BUG-MEDIUM-connection-fix-multiple-handshake-polling-issues.patch deleted file mode 100644 index a6a6042bc2..0000000000 --- a/net/haproxy/patches/021-BUG-MEDIUM-connection-fix-multiple-handshake-polling-issues.patch +++ /dev/null @@ -1,133 +0,0 @@ -commit 30e228120ebc1caad1086d0d90383f472f710375 -Author: Willy Tarreau -Date: Mon Jun 3 08:17:30 2019 +0200 - - BUG/MEDIUM: connection: fix multiple handshake polling issues - - Connection handshakes were rarely stacked on top of each other, but the - recent experiments consisting in sending PROXY over SOCKS4 revealed a - number of issues in these lower layers. First, each handler waiting for - data MUST subscribe to recv events with __conn_sock_want_recv() and MUST - unsubscribe from send events using __conn_sock_stop_send() to avoid any - wake-up loop in case a previous sender has set this. Second, each handler - waiting for sending MUST subscribe to send events with __conn_sock_want_send() - and MUST unsubscribe from recv events using __conn_sock_stop_recv() to - avoid any wake-up loop in case some data are available on the connection. - - Till now this was done at various random places, and in particular the - cases where the FD was not ready for recv forgot to re-enable reading. - - Second, while senders can happily use conn_sock_send() which automatically - handles EINTR, loops, and marks the FD as not ready with fd_cant_send(), - there is no equivalent for recv so receivers facing EAGAIN MUST call - fd_cant_send() to enable polling. It could be argued that implementing - an equivalent conn_sock_recv() function could be useful and more - long-term proof than the current situation. - - Third, both types of handlers MUST unsubscribe from their respective - events once they managed to do their job, and none may even play with - __conn_xprt_*(). Here again this was lacking, and one surprizing call - to __conn_xprt_stop_recv() was present in the proxy protocol parser - for TCP6 messages! - - Thanks to Alexander Liu for his help on this issue. - - This patch must be backported to 1.9 and possibly some older versions, - though the SOCKS parts should be dropped. - - (cherry picked from commit 6499b9d996ea8f57749021f56ed635c4688a727e) - [wt: dropped SOCKS4] - Signed-off-by: Willy Tarreau - (cherry picked from commit a34d37966ed87ffd9924e2b11f8003dc773e1853) - Signed-off-by: Christopher Faulet - -diff --git a/src/connection.c b/src/connection.c -index f57ef60a..e00c2f81 100644 ---- a/src/connection.c -+++ b/src/connection.c -@@ -404,7 +404,7 @@ int conn_recv_proxy(struct connection *conn, int flag) - goto fail; - - if (!fd_recv_ready(conn->handle.fd)) -- return 0; -+ goto not_ready; - - do { - trash.len = recv(conn->handle.fd, trash.str, trash.size, MSG_PEEK); -@@ -413,7 +413,7 @@ int conn_recv_proxy(struct connection *conn, int flag) - continue; - if (errno == EAGAIN) { - fd_cant_recv(conn->handle.fd); -- return 0; -+ goto not_ready; - } - goto recv_abort; - } -@@ -653,8 +653,14 @@ int conn_recv_proxy(struct connection *conn, int flag) - - conn->flags &= ~flag; - conn->flags |= CO_FL_RCVD_PROXY; -+ __conn_sock_stop_recv(conn); - return 1; - -+ not_ready: -+ __conn_sock_want_recv(conn); -+ __conn_sock_stop_send(conn); -+ return 0; -+ - missing: - /* Missing data. Since we're using MSG_PEEK, we can only poll again if - * we have not read anything. Otherwise we need to fail because we won't -@@ -709,7 +715,7 @@ int conn_recv_netscaler_cip(struct connection *conn, int flag) - goto fail; - - if (!fd_recv_ready(conn->handle.fd)) -- return 0; -+ goto not_ready; - - do { - trash.len = recv(conn->handle.fd, trash.str, trash.size, MSG_PEEK); -@@ -718,7 +724,7 @@ int conn_recv_netscaler_cip(struct connection *conn, int flag) - continue; - if (errno == EAGAIN) { - fd_cant_recv(conn->handle.fd); -- return 0; -+ goto not_ready; - } - goto recv_abort; - } -@@ -849,8 +855,14 @@ int conn_recv_netscaler_cip(struct connection *conn, int flag) - } while (0); - - conn->flags &= ~flag; -+ __conn_sock_stop_recv(conn); - return 1; - -+ not_ready: -+ __conn_sock_want_recv(conn); -+ __conn_sock_stop_send(conn); -+ return 0; -+ - missing: - /* Missing data. Since we're using MSG_PEEK, we can only poll again if - * we have not read anything. Otherwise we need to fail because we won't -diff --git a/src/stream_interface.c b/src/stream_interface.c -index 47a100d7..8e4df70a 100644 ---- a/src/stream_interface.c -+++ b/src/stream_interface.c -@@ -400,6 +400,7 @@ int conn_si_send_proxy(struct connection *conn, unsigned int flag) - if (conn->flags & CO_FL_WAIT_L4_CONN) - conn->flags &= ~CO_FL_WAIT_L4_CONN; - conn->flags &= ~flag; -+ __conn_sock_stop_send(conn); - return 1; - - out_error: -@@ -409,6 +410,7 @@ int conn_si_send_proxy(struct connection *conn, unsigned int flag) - - out_wait: - __conn_sock_stop_recv(conn); -+ __conn_sock_want_send(conn); - return 0; - } - diff --git a/net/haproxy/patches/022-BUG-MEDIUM-vars-make-sure-the-scope-is-always-valid-when-accessing-vars.patch b/net/haproxy/patches/022-BUG-MEDIUM-vars-make-sure-the-scope-is-always-valid-when-accessing-vars.patch deleted file mode 100644 index 5312464a8d..0000000000 --- a/net/haproxy/patches/022-BUG-MEDIUM-vars-make-sure-the-scope-is-always-valid-when-accessing-vars.patch +++ /dev/null @@ -1,193 +0,0 @@ -commit 47133bd99225554519c1d32293e0e5c3db83db30 -Author: Willy Tarreau -Date: Tue Jun 4 16:27:36 2019 +0200 - - BUG/MEDIUM: vars: make sure the scope is always valid when accessing vars - - Patrick Hemmer reported that a simple tcp rule involving a variable like - this is enough to crash haproxy : - - frontend foo - bind :8001 - tcp-request session set-var(txn.foo) src - - The tests on the variables scopes is not strict enough, it needs to always - verify if the stream is valid when accessing a req/res/txn variable. This - patch does this by adding a new get_vars() function which does the job - instead of open-coding all the lookups everywhere. - - It must be backported to all versions supporting set-var and - "tcp-request session" so at least 1.9 and 1.8. - - (cherry picked from commit f37b140b06b9963dea8adaf5e13b5b57cd219c74) - [wt: s/_HA_/HA_/] - Signed-off-by: Willy Tarreau - (cherry picked from commit 5dcf8515592602ed0d962e365cbb74a3646727c1) - Signed-off-by: Christopher Faulet - -diff --git a/src/vars.c b/src/vars.c -index 566ead6e..c86f612f 100644 ---- a/src/vars.c -+++ b/src/vars.c -@@ -34,6 +34,25 @@ static unsigned int var_reqres_limit = 0; - - __decl_hathreads(HA_RWLOCK_T var_names_rwlock); - -+/* returns the struct vars pointer for a session, stream and scope, or NULL if -+ * it does not exist. -+ */ -+static inline struct vars *get_vars(struct session *sess, struct stream *strm, enum vars_scope scope) -+{ -+ switch (scope) { -+ case SCOPE_PROC: -+ return &global.vars; -+ case SCOPE_SESS: -+ return &sess->vars; -+ case SCOPE_TXN: -+ return strm ? &strm->vars_txn : NULL; -+ case SCOPE_REQ: -+ case SCOPE_RES: -+ default: -+ return strm ? &strm->vars_reqres : NULL; -+ } -+} -+ - /* This function adds or remove memory size from the accounting. The inner - * pointers may be null when setting the outer ones only. - */ -@@ -42,10 +61,12 @@ static void var_accounting_diff(struct vars *vars, struct session *sess, struct - switch (vars->scope) { - case SCOPE_REQ: - case SCOPE_RES: -- HA_ATOMIC_ADD(&strm->vars_reqres.size, size); -+ if (strm) -+ HA_ATOMIC_ADD(&strm->vars_reqres.size, size); - /* fall through */ - case SCOPE_TXN: -- HA_ATOMIC_ADD(&strm->vars_txn.size, size); -+ if (strm) -+ HA_ATOMIC_ADD(&strm->vars_txn.size, size); - /* fall through */ - case SCOPE_SESS: - HA_ATOMIC_ADD(&sess->vars.size, size); -@@ -68,11 +89,11 @@ static int var_accounting_add(struct vars *vars, struct session *sess, struct st - switch (vars->scope) { - case SCOPE_REQ: - case SCOPE_RES: -- if (var_reqres_limit && strm->vars_reqres.size + size > var_reqres_limit) -+ if (var_reqres_limit && strm && strm->vars_reqres.size + size > var_reqres_limit) - return 0; - /* fall through */ - case SCOPE_TXN: -- if (var_txn_limit && strm->vars_txn.size + size > var_txn_limit) -+ if (var_txn_limit && strm && strm->vars_txn.size + size > var_txn_limit) - return 0; - /* fall through */ - case SCOPE_SESS: -@@ -285,27 +306,8 @@ static int smp_fetch_var(const struct arg *args, struct sample *smp, const char - struct vars *vars; - - /* Check the availibity of the variable. */ -- switch (var_desc->scope) { -- case SCOPE_PROC: -- vars = &global.vars; -- break; -- case SCOPE_SESS: -- vars = &smp->sess->vars; -- break; -- case SCOPE_TXN: -- if (!smp->strm) -- return 0; -- vars = &smp->strm->vars_txn; -- break; -- case SCOPE_REQ: -- case SCOPE_RES: -- default: -- if (!smp->strm) -- return 0; -- vars = &smp->strm->vars_reqres; -- break; -- } -- if (vars->scope != var_desc->scope) -+ vars = get_vars(smp->sess, smp->strm, var_desc->scope); -+ if (!vars || vars->scope != var_desc->scope) - return 0; - - HA_RWLOCK_RDLOCK(VARS_LOCK, &vars->rwlock); -@@ -423,15 +425,8 @@ static inline int sample_store_stream(const char *name, enum vars_scope scope, s - struct vars *vars; - int ret; - -- switch (scope) { -- case SCOPE_PROC: vars = &global.vars; break; -- case SCOPE_SESS: vars = &smp->sess->vars; break; -- case SCOPE_TXN: vars = &smp->strm->vars_txn; break; -- case SCOPE_REQ: -- case SCOPE_RES: -- default: vars = &smp->strm->vars_reqres; break; -- } -- if (vars->scope != scope) -+ vars = get_vars(smp->sess, smp->strm, scope); -+ if (!vars || vars->scope != scope) - return 0; - - HA_RWLOCK_WRLOCK(VARS_LOCK, &vars->rwlock); -@@ -447,15 +442,8 @@ static inline int sample_clear_stream(const char *name, enum vars_scope scope, s - struct var *var; - unsigned int size = 0; - -- switch (scope) { -- case SCOPE_PROC: vars = &global.vars; break; -- case SCOPE_SESS: vars = &smp->sess->vars; break; -- case SCOPE_TXN: vars = &smp->strm->vars_txn; break; -- case SCOPE_REQ: -- case SCOPE_RES: -- default: vars = &smp->strm->vars_reqres; break; -- } -- if (vars->scope != scope) -+ vars = get_vars(smp->sess, smp->strm, scope); -+ if (!vars || vars->scope != scope) - return 0; - - /* Look for existing variable name. */ -@@ -586,17 +574,8 @@ int vars_get_by_name(const char *name, size_t len, struct sample *smp) - return 0; - - /* Select "vars" pool according with the scope. */ -- switch (scope) { -- case SCOPE_PROC: vars = &global.vars; break; -- case SCOPE_SESS: vars = &smp->sess->vars; break; -- case SCOPE_TXN: vars = &smp->strm->vars_txn; break; -- case SCOPE_REQ: -- case SCOPE_RES: -- default: vars = &smp->strm->vars_reqres; break; -- } -- -- /* Check if the scope is avalaible a this point of processing. */ -- if (vars->scope != scope) -+ vars = get_vars(smp->sess, smp->strm, scope); -+ if (!vars || vars->scope != scope) - return 0; - - /* Get the variable entry. */ -@@ -620,17 +599,10 @@ int vars_get_by_desc(const struct var_desc *var_desc, struct sample *smp) - struct var *var; - - /* Select "vars" pool according with the scope. */ -- switch (var_desc->scope) { -- case SCOPE_PROC: vars = &global.vars; break; -- case SCOPE_SESS: vars = &smp->sess->vars; break; -- case SCOPE_TXN: vars = &smp->strm->vars_txn; break; -- case SCOPE_REQ: -- case SCOPE_RES: -- default: vars = &smp->strm->vars_reqres; break; -- } -+ vars = get_vars(smp->sess, smp->strm, var_desc->scope); - -- /* Check if the scope is avalaible a this point of processing. */ -- if (vars->scope != var_desc->scope) -+ /* Check if the scope is available a this point of processing. */ -+ if (!vars || vars->scope != var_desc->scope) - return 0; - - /* Get the variable entry. */ diff --git a/net/haproxy/patches/023-BUG-MEDIUM-vars-make-the-tcp-http-unset-var-action-support-conditions.patch b/net/haproxy/patches/023-BUG-MEDIUM-vars-make-the-tcp-http-unset-var-action-support-conditions.patch deleted file mode 100644 index 6c98beb12a..0000000000 --- a/net/haproxy/patches/023-BUG-MEDIUM-vars-make-the-tcp-http-unset-var-action-support-conditions.patch +++ /dev/null @@ -1,44 +0,0 @@ -commit a41ac2d710711f3ab91d92415278a73c358aedca -Author: Willy Tarreau -Date: Tue Jun 4 16:43:29 2019 +0200 - - BUG/MEDIUM: vars: make the tcp/http unset-var() action support conditions - - Patrick Hemmer reported that http-request unset-var(foo) if ... fails to - parse. The reason is that it reuses the same parser as "set-var(foo)" which - makes a special case of the arguments, supposed to be a sample expression - for set-var, but which must not exist for unset-var. Unfortunately the - parser finds "if" or "unless" and believes it's an expression. Let's simply - drop the test so that the outer rule parser deals with potential extraneous - keywords. - - This should be backported to all versions supporting unset-var(). - - (cherry picked from commit 4b7531f48b5aa66d11fcee2836c201644bfb6a71) - Signed-off-by: Willy Tarreau - (cherry picked from commit a47e745276662db361637914b8558984f091306b) - Signed-off-by: Christopher Faulet - -diff --git a/src/vars.c b/src/vars.c -index c86f612f..d69fb838 100644 ---- a/src/vars.c -+++ b/src/vars.c -@@ -684,6 +684,7 @@ static int conv_check_var(struct arg *args, struct sample_conv *conv, - * the format: - * - * set-var() -+ * unset-var() - * - * It returns ACT_RET_PRS_ERR if fails and is filled with an error - * message. Otherwise, it returns ACT_RET_PRS_OK and the variable -@@ -727,10 +728,6 @@ static enum act_parse_ret parse_store(const char **args, int *arg, struct proxy - /* There is no fetch method when variable is unset. Just set the right - * action and return. */ - if (!set_var) { -- if (*args[*arg]) { -- memprintf(err, "fetch method not supported"); -- return ACT_RET_PRS_ERR; -- } - rule->action = ACT_CUSTOM; - rule->action_ptr = action_clear; - return ACT_RET_PRS_OK; diff --git a/net/haproxy/patches/024-BUG-MEDIUM-mux-h2-make-sure-the-connection-timeout-is-always-set.patch b/net/haproxy/patches/024-BUG-MEDIUM-mux-h2-make-sure-the-connection-timeout-is-always-set.patch deleted file mode 100644 index 6c47f2f250..0000000000 --- a/net/haproxy/patches/024-BUG-MEDIUM-mux-h2-make-sure-the-connection-timeout-is-always-set.patch +++ /dev/null @@ -1,73 +0,0 @@ -commit e7c30a33646f4ec73041ea57bd9fdcdc3e4a80ab -Author: Willy Tarreau -Date: Fri Jun 7 08:20:46 2019 +0200 - - BUG/MEDIUM: mux-h2: make sure the connection timeout is always set - - There seems to be a tricky case in the H2 mux related to stream flow - control versus buffer a full situation : is a large response cannot - be entirely sent to the client due to the stream window being too - small, the stream is paused with the SFCTL flag. Then the upper - layer stream might get bored and expire this stream. It will then - shut it down first. But the shutdown operation might fail if the - mux buffer is full, resulting in the h2s being subscribed to the - deferred_shut event with the stream *not* added to the send_list - since it's blocked in SFCTL. In the mean time the upper layer completely - closes, calling h2_detach(). There we have a send_wait (the pending - shutw), the stream is marked with SFCTL so we orphan it. - - Then if the client finally reads all the data that were clogging the - buffer, the send_list is run again, but our stream is not there. From - this point, the connection's stream list is not empty, the mux buffer - is empty, so the connection's timeout is not set. If the client - disappears without updating the stream's window, nothing will expire - the connection. - - This patch makes sure we always keep the connection timeout updated. - There might be finer solutions, such as checking that there are still - living streams in the connection (i.e. streams not blocked in SFCTL - state), though this is not necessarily trivial nor useful, since the - client timeout is the same for the upper level stream and the connection - anyway. - - This patch needs to be backported to 1.9 and 1.8 after some observation. - - (cherry picked from commit 7348119fb22bf761c33e06e8a092bd006660cc81) - Signed-off-by: Christopher Faulet - (cherry picked from commit e76090f78b6b8c519abf20061bfc5a4423816ea5) - Signed-off-by: Christopher Faulet - -diff --git a/src/mux_h2.c b/src/mux_h2.c -index b2f3096e..985b9742 100644 ---- a/src/mux_h2.c -+++ b/src/mux_h2.c -@@ -2406,12 +2406,8 @@ static int h2_wake(struct connection *conn) - } - - if (h2c->task) { -- if (eb_is_empty(&h2c->streams_by_id) || h2c->mbuf->o) { -- h2c->task->expire = tick_add(now_ms, h2c->last_sid < 0 ? h2c->timeout : h2c->shut_timeout); -- task_queue(h2c->task); -- } -- else -- h2c->task->expire = TICK_ETERNITY; -+ h2c->task->expire = tick_add(now_ms, h2c->last_sid < 0 ? h2c->timeout : h2c->shut_timeout); -+ task_queue(h2c->task); - } - return 0; - } -@@ -2587,12 +2583,8 @@ static void h2_detach(struct conn_stream *cs) - h2_release(h2c->conn); - } - else if (h2c->task) { -- if (eb_is_empty(&h2c->streams_by_id) || h2c->mbuf->o) { -- h2c->task->expire = tick_add(now_ms, h2c->last_sid < 0 ? h2c->timeout : h2c->shut_timeout); -- task_queue(h2c->task); -- } -- else -- h2c->task->expire = TICK_ETERNITY; -+ h2c->task->expire = tick_add(now_ms, h2c->last_sid < 0 ? h2c->timeout : h2c->shut_timeout); -+ task_queue(h2c->task); - } - } - diff --git a/net/haproxy/patches/025-BUG-MINOR-http-rules-mention-deny_status-for-deny-in-the-error-message.patch b/net/haproxy/patches/025-BUG-MINOR-http-rules-mention-deny_status-for-deny-in-the-error-message.patch deleted file mode 100644 index d907153f34..0000000000 --- a/net/haproxy/patches/025-BUG-MINOR-http-rules-mention-deny_status-for-deny-in-the-error-message.patch +++ /dev/null @@ -1,34 +0,0 @@ -commit 8a74cad9b7fe8b9e1f5b140d90360ece838a878e -Author: Willy Tarreau -Date: Tue Jun 11 16:01:56 2019 +0200 - - BUG/MINOR: http-rules: mention "deny_status" for "deny" in the error message - - The error message indicating an unknown keyword on an http-request rule - doesn't mention the "deny_status" option which comes with the "deny" rule, - this is particularly confusing. - - This can be backported to all versions supporting this option. - - (cherry picked from commit 5abdc760c99a0011607f2cc97e199ef6ce0e8486) - Signed-off-by: Christopher Faulet - (cherry picked from commit 4e66beaf2a32bd835db9de61a60318648258f649) - Signed-off-by: Christopher Faulet - - [Cf: The fix was applied on src/proto_http.c because, in 1.8, the file - src/http_rules.c does not exist.] - -diff --git a/src/proto_http.c b/src/proto_http.c -index e5792f8c..689e0e31 100644 ---- a/src/proto_http.c -+++ b/src/proto_http.c -@@ -8830,7 +8830,8 @@ struct act_rule *parse_http_req_cond(const char **args, const char *file, int li - rule->cond = cond; - } - else if (*args[cur_arg]) { -- ha_alert("parsing [%s:%d]: 'http-request %s' expects 'realm' for 'auth' or" -+ ha_alert("parsing [%s:%d]: 'http-request %s' expects 'realm' for 'auth'," -+ " 'deny_status' for 'deny', or" - " either 'if' or 'unless' followed by a condition but found '%s'.\n", - file, linenum, args[0], args[cur_arg]); - goto out_err; diff --git a/net/haproxy/patches/026-MINOR-doc-Remove--Ds-option-in-man-page.patch b/net/haproxy/patches/026-MINOR-doc-Remove--Ds-option-in-man-page.patch deleted file mode 100644 index 44006f2cdb..0000000000 --- a/net/haproxy/patches/026-MINOR-doc-Remove--Ds-option-in-man-page.patch +++ /dev/null @@ -1,30 +0,0 @@ -commit 8f2772f5c603168ad3f79adc9e17569f510274ca -Author: Kazuo Yagi -Date: Thu Jun 13 17:14:57 2019 +0900 - - MINOR: doc: Remove -Ds option in man page - - Remove -Ds option in man page. - - Should be backported in every version since 1.8. - - (cherry picked from commit 971c3943be1283e9d377d68f95ea467304b3a8da) - Signed-off-by: Christopher Faulet - (cherry picked from commit a5e78ea5150f31190e4c1cd38fa7c1cadbf1ae8a) - Signed-off-by: Christopher Faulet - -diff --git a/doc/haproxy.1 b/doc/haproxy.1 -index 91f58a3b..cfed2cf7 100644 ---- a/doc/haproxy.1 -+++ b/doc/haproxy.1 -@@ -77,10 +77,6 @@ starting up. - \fB\-D\fP - Start in daemon mode. - --.TP --\fB\-Ds\fP --Start in systemd daemon mode, keeping a process in foreground. -- - .TP - \fB\-q\fP - Disable messages on output. diff --git a/net/haproxy/patches/027-MINOR-doc-add-master-worker-in-the-man-page.patch b/net/haproxy/patches/027-MINOR-doc-add-master-worker-in-the-man-page.patch deleted file mode 100644 index 61e8ad0ada..0000000000 --- a/net/haproxy/patches/027-MINOR-doc-add-master-worker-in-the-man-page.patch +++ /dev/null @@ -1,55 +0,0 @@ -commit 4fb0b5fb585e7f697914e935fe1001f752da8470 -Author: William Lallemand -Date: Thu Jun 13 11:51:09 2019 +0200 - - MINOR: doc: add master-worker in the man page - - Add some information about the master-worker in the man page. - - Should be backported in every version since 1.8. - - (cherry picked from commit 95635ddac8c29859d297e8ba33174e71efd5fc47) - Signed-off-by: Christopher Faulet - (cherry picked from commit d7a0c4695f00765dc03d7d6f6e17058726e84951) - Signed-off-by: Christopher Faulet - -diff --git a/doc/haproxy.1 b/doc/haproxy.1 -index cfed2cf7..2a23674f 100644 ---- a/doc/haproxy.1 -+++ b/doc/haproxy.1 -@@ -6,7 +6,7 @@ HAProxy \- fast and reliable http reverse proxy and load balancer - - .SH SYNOPSIS - --haproxy \-f [\-L\ ] [\-n\ maxconn] [\-N\ maxconn] [\-C\ ] [\-v|\-vv] [\-d] [\-D] [\-q] [\-V] [\-c] [\-p\ ] [\-dk] [\-ds] [\-de] [\-dp] [\-db] [\-dM[]] [\-m\ ] [\-x ] [{\-sf|\-st}\ pidlist...] -+haproxy \-f [\-L\ ] [\-n\ maxconn] [\-N\ maxconn] [\-C\ ] [\-v|\-vv] [\-d] [\-D] [\-W] [\-Ws] [\-q] [\-V] [\-c] [\-p\ ] [\-dk] [\-ds] [\-de] [\-dp] [\-db] [\-dM[]] [\-m\ ] [\-x ] [{\-sf|\-st}\ pidlist...] - - .SH DESCRIPTION - -@@ -77,6 +77,16 @@ starting up. - \fB\-D\fP - Start in daemon mode. - -+.TP -+\fB\-W\fP -+Start in master-worker mode. Could be used either with foreground or daemon -+mode. -+ -+.TP -+\fB\-Ws\fP -+Start in master-worker mode with systemd notify support. It tells systemd when -+the process is ready. This mode forces foreground. -+ - .TP - \fB\-q\fP - Disable messages on output. -@@ -172,6 +182,9 @@ Some signals have a special meaning for the haproxy daemon. Generally, they are - \- \fBSIGUSR1\fP - Tells the daemon to stop all proxies and exit once all sessions are closed. It is often referred to as the "soft-stop" signal. - .TP -+\- \fBSIGUSR2\fP -+In master-worker mode, reloads the configuration and sends a soft-stop signal to old processes. -+.TP - \- \fBSIGTTOU\fP - Tells the daemon to stop listening to all sockets. Used internally by \fB\-sf\fP and \fB\-st\fP. - .TP diff --git a/net/haproxy/patches/028-BUG-MEDIUM-compression-Set-Vary-Accept-Encoding-for-compressed-responses.patch b/net/haproxy/patches/028-BUG-MEDIUM-compression-Set-Vary-Accept-Encoding-for-compressed-responses.patch deleted file mode 100644 index 2c104636de..0000000000 --- a/net/haproxy/patches/028-BUG-MEDIUM-compression-Set-Vary-Accept-Encoding-for-compressed-responses.patch +++ /dev/null @@ -1,249 +0,0 @@ -commit a27131f6e1e6c3e16e056915ba5ec2c560051296 -Author: Tim Duesterhus -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 - (cherry picked from commit eaf650083924a697cde3379703984c5e7a5ebd41) - Signed-off-by: Christopher Faulet - (cherry picked from commit 96942d657ec7f29a328a5759558dbaa26d8e3e53) - Signed-off-by: Christopher Faulet - - [Cf: The patch was updated because there is no HTX in 1.8] - -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 == "" -+ 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 == "" -+ 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 == "" -+ expect resp.bodylen == 100 -+ -+ txreq -url "/plain/accept-encoding-null" -+ rxresp -+ expect resp.status == 200 -+ expect resp.http.vary == "" -+ expect resp.bodylen == 100 -+ -+ txreq -url "/html/accept-encoding-gzip" \ -+ -hdr "Accept-Encoding: gzip" -+ rxresp -+ expect resp.status == 200 -+ expect resp.http.vary == "" -+ expect resp.bodylen == 100 -+ -+ txreq -url "/html/accept-encoding-invalid" \ -+ -hdr "Accept-Encoding: invalid" -+ rxresp -+ expect resp.status == 200 -+ expect resp.http.vary == "" -+ expect resp.bodylen == 100 -+ -+ txreq -url "/html/accept-encoding-null" -+ rxresp -+ expect resp.status == 200 -+ expect resp.http.vary == "" -+ expect resp.bodylen == 100 -+ -+ txreq -url "/dup-etag/accept-encoding-gzip" \ -+ -hdr "Accept-Encoding: gzip" -+ rxresp -+ expect resp.status == 200 -+ expect resp.http.vary == "" -+ 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 == "" -+ expect resp.bodylen == 100 -+ -+ txreq -url "/plain/accept-encoding-invalid" \ -+ -hdr "Accept-Encoding: invalid" -+ rxresp -+ expect resp.status == 200 -+ expect resp.http.vary == "" -+ expect resp.bodylen == 100 -+ -+ txreq -url "/plain/accept-encoding-null" -+ rxresp -+ expect resp.status == 200 -+ expect resp.http.vary == "" -+ expect resp.bodylen == 100 -+ -+ txreq -url "/html/accept-encoding-gzip" \ -+ -hdr "Accept-Encoding: gzip" -+ rxresp -+ expect resp.status == 200 -+ expect resp.http.vary == "" -+ expect resp.bodylen == 100 -+ -+ txreq -url "/html/accept-encoding-invalid" \ -+ -hdr "Accept-Encoding: invalid" -+ rxresp -+ expect resp.status == 200 -+ expect resp.http.vary == "" -+ expect resp.bodylen == 100 -+ -+ txreq -url "/html/accept-encoding-null" -+ rxresp -+ expect resp.status == 200 -+ expect resp.http.vary == "" -+ expect resp.bodylen == 100 -+ -+ txreq -url "/dup-etag/accept-encoding-gzip" \ -+ -hdr "Accept-Encoding: gzip" -+ rxresp -+ expect resp.status == 200 -+ expect resp.http.vary == "" -+ expect resp.bodylen == 100 -+} -run -diff --git a/src/flt_http_comp.c b/src/flt_http_comp.c -index b93ff69e..b48a4491 100644 ---- a/src/flt_http_comp.c -+++ b/src/flt_http_comp.c -@@ -555,6 +555,9 @@ select_compression_response_header(struct comp_state *st, struct stream *s, stru - if (!(msg->flags & HTTP_MSGF_TE_CHNK)) - http_header_add_tail2(&txn->rsp, &txn->hdr_idx, "Transfer-Encoding: chunked", 26); - -+ /* add Vary header */ -+ if (http_header_add_tail2(&txn->rsp, &txn->hdr_idx, "Vary: Accept-Encoding", 21) < 0) -+ goto fail; - /* - * Add Content-Encoding header when it's not identity encoding. - * RFC 2616 : Identity encoding: This content-coding is used only in the