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