Merge ~lucaskanashiro/ubuntu/+source/haproxy:kinetic-mre into ubuntu/+source/haproxy:ubuntu/kinetic-devel

Proposed by Lucas Kanashiro
Status: Merged
Approved by: git-ubuntu bot
Approved revision: not available
Merge reported by: Lucas Kanashiro
Merged at revision: 7e46924b5a654ab811b04f3b8f1bee1eca8b7388
Proposed branch: ~lucaskanashiro/ubuntu/+source/haproxy:kinetic-mre
Merge into: ubuntu/+source/haproxy:ubuntu/kinetic-devel
Diff against target: 6773 lines (+2423/-819)
114 files modified
.cirrus.yml (+1/-1)
.github/matrix.py (+10/-7)
.github/workflows/compliance.yml (+2/-2)
.github/workflows/cross-zoo.yml (+110/-0)
.github/workflows/vtest.yml (+5/-2)
.github/workflows/windows.yml (+2/-1)
CHANGELOG (+190/-0)
Makefile (+7/-3)
SUBVERS (+1/-1)
VERDATE (+2/-2)
VERSION (+1/-1)
addons/promex/README (+2/-0)
addons/promex/service-prometheus.c (+30/-1)
addons/wurfl/dummy/wurfl/wurfl.h (+10/-5)
debian/changelog (+20/-0)
debian/patches/reproducible.patch (+1/-3)
debian/patches/series (+0/-3)
dev/null (+0/-145)
doc/configuration.txt (+282/-224)
doc/intro.txt (+1/-1)
doc/management.txt (+4/-0)
doc/proxy-protocol.txt (+1/-1)
include/haproxy/buf.h (+1/-1)
include/haproxy/bug.h (+2/-0)
include/haproxy/http.h (+2/-0)
include/haproxy/listener-t.h (+11/-2)
include/haproxy/listener.h (+11/-5)
include/haproxy/peers-t.h (+1/-0)
include/haproxy/pool.h (+2/-2)
include/haproxy/server.h (+9/-5)
include/haproxy/sink.h (+2/-0)
include/haproxy/ssl_sock-t.h (+11/-7)
include/haproxy/ssl_sock.h (+23/-0)
include/haproxy/stats-t.h (+2/-0)
include/haproxy/stream.h (+1/-1)
include/haproxy/task.h (+2/-1)
include/haproxy/tcpcheck-t.h (+1/-0)
include/haproxy/tools.h (+3/-2)
include/import/ebmbtree.h (+53/-0)
reg-tests/cache/if-modified-since.vtc (+4/-1)
reg-tests/cache/if-none-match.vtc (+4/-0)
reg-tests/checks/4be_1srv_smtpchk_httpchk_layer47errors.vtc (+8/-3)
reg-tests/checks/pgsql-check.vtc (+16/-0)
reg-tests/checks/smtp-check.vtc (+6/-2)
reg-tests/contrib/prometheus.vtc (+4/-3)
reg-tests/converter/digest.vtc (+1/-1)
reg-tests/converter/hmac.vtc (+1/-1)
reg-tests/converter/iif.vtc (+1/-1)
reg-tests/converter/json_query.vtc (+1/-1)
reg-tests/http-messaging/h1_host_normalization.vtc (+276/-0)
reg-tests/http-messaging/http_request_buffer.vtc (+18/-1)
reg-tests/http-rules/restrict_req_hdr_names.vtc (+62/-0)
reg-tests/log/log_forward.vtc (+57/-0)
reg-tests/mailers/healthcheckmail.vtc (+1/-1)
reg-tests/ssl/log_forward_ssl.vtc (+60/-0)
reg-tests/startup/automatic_maxconn.vtc (+102/-0)
reg-tests/startup/common.pem (+117/-0)
scripts/announce-release (+12/-11)
src/backend.c (+0/-1)
src/cache.c (+17/-17)
src/cfgparse-listen.c (+4/-2)
src/cfgparse-ssl.c (+7/-7)
src/cfgparse.c (+52/-5)
src/check.c (+7/-0)
src/dns.c (+1/-1)
src/ev_epoll.c (+2/-2)
src/ev_evports.c (+2/-4)
src/ev_kqueue.c (+2/-2)
src/ev_poll.c (+2/-1)
src/fcgi-app.c (+1/-1)
src/fcgi.c (+6/-2)
src/fd.c (+3/-3)
src/flt_http_comp.c (+21/-21)
src/flt_spoe.c (+22/-9)
src/h1.c (+92/-15)
src/h1_htx.c (+3/-0)
src/haproxy.c (+10/-2)
src/hlua.c (+8/-3)
src/hlua_fcn.c (+3/-0)
src/hpack-dec.c (+10/-0)
src/http.c (+32/-0)
src/http_act.c (+2/-0)
src/http_ana.c (+20/-14)
src/http_fetch.c (+6/-5)
src/http_htx.c (+14/-25)
src/listener.c (+45/-16)
src/log.c (+11/-5)
src/mux_fcgi.c (+14/-8)
src/mux_h1.c (+26/-13)
src/mux_h2.c (+24/-10)
src/mworker.c (+4/-2)
src/pattern.c (+6/-6)
src/peers.c (+41/-25)
src/pool.c (+12/-12)
src/proto_tcp.c (+9/-6)
src/proto_udp.c (+8/-5)
src/protocol.c (+3/-3)
src/proxy.c (+32/-16)
src/regex.c (+9/-5)
src/resolvers.c (+29/-10)
src/ring.c (+11/-1)
src/server.c (+5/-6)
src/signal.c (+3/-0)
src/sink.c (+46/-15)
src/ssl_crtlist.c (+5/-0)
src/ssl_sample.c (+3/-0)
src/ssl_sock.c (+17/-11)
src/stats.c (+20/-5)
src/stick_table.c (+29/-17)
src/stream.c (+22/-12)
src/stream_interface.c (+28/-4)
src/tcpcheck.c (+37/-6)
src/time.c (+1/-0)
src/tools.c (+4/-3)
Reviewer Review Type Date Requested Status
git-ubuntu bot Approve
Andreas Hasenack Approve
Canonical Server Reporter Pending
Review via email: mp+439425@code.launchpad.net

Description of the change

MRE update to version 2.4.22 (LP: #2012557). Some patches were removed (applied by upstream) and others refreshed.

the proposed package is available in this PPA:

https://launchpad.net/~lucaskanashiro/+archive/ubuntu/ha-stack

autopkgtest summary:

autopkgtest [18:52:16]: @@@@@@@@@@@@@@@@@@@@ summary
cli PASS
proxy-localhost PASS
proxy-ssl-termination PASS
proxy-ssl-pass-through PASS

To post a comment you must log in.
Revision history for this message
Andreas Hasenack (ahasenack) wrote :

This needs rebasing, security released 2.4.18-1ubuntu1.3

Revision history for this message
Lucas Kanashiro (lucaskanashiro) wrote :

Thanks for checking Andreas, the rebase is done.

Revision history for this message
Andreas Hasenack (ahasenack) :
review: Needs Information
Revision history for this message
Lucas Kanashiro (lucaskanashiro) :
Revision history for this message
Andreas Hasenack (ahasenack) :
Revision history for this message
Lucas Kanashiro (lucaskanashiro) :
Revision history for this message
Lucas Kanashiro (lucaskanashiro) :
Revision history for this message
Andreas Hasenack (ahasenack) :
Revision history for this message
Lucas Kanashiro (lucaskanashiro) wrote :

Version string fixed.

Revision history for this message
Andreas Hasenack (ahasenack) wrote :

haha, gotta love version strings :)

+1

review: Approve
Revision history for this message
git-ubuntu bot (git-ubuntu-bot) wrote :

Approvers: lucaskanashiro, ahasenack
Uploaders: lucaskanashiro, ahasenack
MP auto-approved

review: Approve
Revision history for this message
Lucas Kanashiro (lucaskanashiro) wrote :

Thanks Andreas. Package uploaded:

Uploading haproxy_2.4.22-0ubuntu0.22.10.1.dsc
Uploading haproxy_2.4.22.orig.tar.gz
Uploading haproxy_2.4.22-0ubuntu0.22.10.1.debian.tar.xz
Uploading haproxy_2.4.22-0ubuntu0.22.10.1_source.changes

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/.cirrus.yml b/.cirrus.yml
index e754f83..deace96 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -1,7 +1,7 @@
1FreeBSD_task:1FreeBSD_task:
2 freebsd_instance:2 freebsd_instance:
3 matrix:3 matrix:
4 image_family: freebsd-13-04 image_family: freebsd-13-1
5 only_if: $CIRRUS_BRANCH =~ 'master|next'5 only_if: $CIRRUS_BRANCH =~ 'master|next'
6 install_script:6 install_script:
7 - pkg update -f && pkg upgrade -y && pkg install -y openssl git gmake lua53 socat pcre7 - pkg update -f && pkg upgrade -y && pkg install -y openssl git gmake lua53 socat pcre
diff --git a/.github/matrix.py b/.github/matrix.py
index 264a3d2..abd6caf 100644
--- a/.github/matrix.py
+++ b/.github/matrix.py
@@ -10,6 +10,7 @@ import json
10import sys10import sys
11import urllib.request11import urllib.request
12import re12import re
13from os import environ
1314
14if len(sys.argv) == 2:15if len(sys.argv) == 2:
15 build_type = sys.argv[1]16 build_type = sys.argv[1]
@@ -40,7 +41,7 @@ def determine_latest_openssl(ssl):
40 if "openssl-" in name:41 if "openssl-" in name:
41 if name > latest_tag:42 if name > latest_tag:
42 latest_tag = name43 latest_tag = name
43 return "OPENSSL={}".format(latest_tag[8:])44 return "OPENSSL_VERSION={}".format(latest_tag[8:])
4445
45def determine_latest_libressl(ssl):46def determine_latest_libressl(ssl):
46 libressl_download_list = urllib.request.urlopen("http://ftp.openbsd.org/pub/OpenBSD/LibreSSL/")47 libressl_download_list = urllib.request.urlopen("http://ftp.openbsd.org/pub/OpenBSD/LibreSSL/")
@@ -48,7 +49,7 @@ def determine_latest_libressl(ssl):
48 decoded_line = line.decode("utf-8")49 decoded_line = line.decode("utf-8")
49 if "libressl-" in decoded_line and ".tar.gz.asc" in decoded_line:50 if "libressl-" in decoded_line and ".tar.gz.asc" in decoded_line:
50 l = re.split("libressl-|.tar.gz.asc", decoded_line)[1]51 l = re.split("libressl-|.tar.gz.asc", decoded_line)[1]
51 return "LIBRESSL={}".format(l)52 return "LIBRESSL_VERSION={}".format(l)
5253
53def clean_compression(compression):54def clean_compression(compression):
54 return compression.replace("USE_", "").lower()55 return compression.replace("USE_", "").lower()
@@ -67,7 +68,7 @@ matrix = []
6768
68# Ubuntu69# Ubuntu
6970
70os = "ubuntu-latest"71os = "ubuntu-20.04"
71TARGET = "linux-glibc"72TARGET = "linux-glibc"
72for CC in ["gcc", "clang"]:73for CC in ["gcc", "clang"]:
73 matrix.append(74 matrix.append(
@@ -125,8 +126,8 @@ for CC in ["gcc", "clang"]:
125 for ssl in [126 for ssl in [
126 "stock",127 "stock",
127 "OPENSSL_VERSION=1.0.2u",128 "OPENSSL_VERSION=1.0.2u",
128 "OPENSSL_VERSION=latest",129 "OPENSSL_VERSION=3.0.2",
129 "LIBRESSL_VERSION=latest",130 "LIBRESSL_VERSION=3.5.3",
130# "BORINGSSL=yes",131# "BORINGSSL=yes",
131 ]:132 ]:
132 flags = ["USE_OPENSSL=1"]133 flags = ["USE_OPENSSL=1"]
@@ -155,7 +156,7 @@ for CC in ["gcc", "clang"]:
155156
156# ASAN157# ASAN
157158
158os = "ubuntu-latest"159os = "ubuntu-20.04"
159TARGET = "linux-glibc"160TARGET = "linux-glibc"
160for CC in ["gcc","clang"]:161for CC in ["gcc","clang"]:
161 matrix.append(162 matrix.append(
@@ -207,4 +208,6 @@ for CC in ["clang"]:
207208
208print(json.dumps(matrix, indent=4, sort_keys=True))209print(json.dumps(matrix, indent=4, sort_keys=True))
209210
210print("::set-output name=matrix::{}".format(json.dumps({"include": matrix})))211if environ.get('GITHUB_OUTPUT') is not None:
212 with open(environ.get('GITHUB_OUTPUT'), 'a') as f:
213 print("matrix={}".format(json.dumps({"include": matrix})), file=f)
diff --git a/.github/workflows/compliance.yml b/.github/workflows/compliance.yml
index 66bc154..a11f0fa 100644
--- a/.github/workflows/compliance.yml
+++ b/.github/workflows/compliance.yml
@@ -24,7 +24,7 @@ jobs:
24 curl -fsSL https://github.com/summerwind/h2spec/releases/download/${H2SPEC_VERSION}/h2spec_linux_amd64.tar.gz -o h2spec.tar.gz24 curl -fsSL https://github.com/summerwind/h2spec/releases/download/${H2SPEC_VERSION}/h2spec_linux_amd64.tar.gz -o h2spec.tar.gz
25 tar xvf h2spec.tar.gz25 tar xvf h2spec.tar.gz
26 sudo install -m755 h2spec /usr/local/bin/h2spec26 sudo install -m755 h2spec /usr/local/bin/h2spec
27 echo "::set-output name=version::${H2SPEC_VERSION}"27 echo "version=${H2SPEC_VERSION}" >> $GITHUB_OUTPUT
28 - name: Compile HAProxy with ${{ matrix.CC }}28 - name: Compile HAProxy with ${{ matrix.CC }}
29 run: |29 run: |
30 make -j$(nproc) all \30 make -j$(nproc) all \
@@ -47,7 +47,7 @@ jobs:
47 fi47 fi
48 echo "::endgroup::"48 echo "::endgroup::"
49 haproxy -vv49 haproxy -vv
50 echo "::set-output name=version::$(haproxy -v |awk 'NR==1{print $3}')"50 echo "version=$(haproxy -v |awk 'NR==1{print $3}')" >> $GITHUB_OUTPUT
51 - name: Launch HAProxy ${{ steps.show-version.outputs.version }}51 - name: Launch HAProxy ${{ steps.show-version.outputs.version }}
52 run: haproxy -f .github/h2spec.config -D52 run: haproxy -f .github/h2spec.config -D
53 - name: Run h2spec ${{ steps.install-h2spec.outputs.version }}53 - name: Run h2spec ${{ steps.install-h2spec.outputs.version }}
diff --git a/.github/workflows/cross-zoo.yml b/.github/workflows/cross-zoo.yml
54new file mode 10064454new file mode 100644
index 0000000..e2a5816
--- /dev/null
+++ b/.github/workflows/cross-zoo.yml
@@ -0,0 +1,110 @@
1#
2# this is naamed "zoo" after OpenSSL "cross zoo pipeline"
3#
4name: Cross Compile
5
6on:
7 schedule:
8 - cron: "0 0 21 * *"
9
10permissions:
11 contents: read
12
13jobs:
14 cross-compilation:
15 strategy:
16 matrix:
17 platform: [
18 {
19 arch: aarch64-linux-gnu,
20 libs: libc6-dev-arm64-cross,
21 target: linux-aarch64
22 }, {
23 arch: alpha-linux-gnu,
24 libs: libc6.1-dev-alpha-cross,
25 target: linux-alpha-gcc
26 }, {
27 arch: arm-linux-gnueabi,
28 libs: libc6-dev-armel-cross,
29 target: linux-armv4
30 }, {
31 arch: arm-linux-gnueabihf,
32 libs: libc6-dev-armhf-cross,
33 target: linux-armv4
34 }, {
35 arch: hppa-linux-gnu,
36 libs: libc6-dev-hppa-cross,
37 target: -static linux-generic32
38 }, {
39 arch: m68k-linux-gnu,
40 libs: libc6-dev-m68k-cross,
41 target: -static -m68040 linux-latomic
42 }, {
43 arch: mips-linux-gnu,
44 libs: libc6-dev-mips-cross,
45 target: -static linux-mips32
46 }, {
47 arch: mips64-linux-gnuabi64,
48 libs: libc6-dev-mips64-cross,
49 target: -static linux64-mips64
50 }, {
51 arch: mipsel-linux-gnu,
52 libs: libc6-dev-mipsel-cross,
53 target: linux-mips32
54 }, {
55 arch: powerpc64le-linux-gnu,
56 libs: libc6-dev-ppc64el-cross,
57 target: linux-ppc64le
58 }, {
59 arch: riscv64-linux-gnu,
60 libs: libc6-dev-riscv64-cross,
61 target: linux64-riscv64
62 }, {
63 arch: s390x-linux-gnu,
64 libs: libc6-dev-s390x-cross,
65 target: linux64-s390x
66 }, {
67 arch: sh4-linux-gnu,
68 libs: libc6-dev-sh4-cross,
69 target: no-async linux-latomic
70 }, {
71 arch: hppa-linux-gnu,
72 libs: libc6-dev-hppa-cross,
73 target: linux-generic32,
74 }, {
75 arch: m68k-linux-gnu,
76 libs: libc6-dev-m68k-cross,
77 target: -mcfv4e linux-latomic
78 }, {
79 arch: mips-linux-gnu,
80 libs: libc6-dev-mips-cross,
81 target: linux-mips32
82 }, {
83 arch: mips64-linux-gnuabi64,
84 libs: libc6-dev-mips64-cross,
85 target: linux64-mips64
86 }, {
87 arch: sparc64-linux-gnu,
88 libs: libc6-dev-sparc64-cross,
89 target: linux64-sparcv9
90 }
91 ]
92 runs-on: ubuntu-latest
93 steps:
94 - name: install packages
95 run: |
96 sudo apt-get update
97 sudo apt-get -yq --force-yes install \
98 gcc-${{ matrix.platform.arch }} \
99 ${{ matrix.platform.libs }}
100 - uses: actions/checkout@v2
101
102
103 - name: install quictls
104 run: |
105 QUICTLS_EXTRA_ARGS="--cross-compile-prefix=${{ matrix.platform.arch }}- ${{ matrix.platform.target }}" QUICTLS=yes scripts/build-ssl.sh
106
107 - name: Build
108 run: |
109 make ERR=1 CC=${{ matrix.platform.arch }}-gcc TARGET=linux-glibc USE_LIBCRYPT= USE_OPENSSL=1 USE_QUIC=1 USE_PROMEX=1 SSL_LIB=${HOME}/opt/lib SSL_INC=${HOME}/opt/include ADDLIB="-Wl,-rpath,${HOME}/opt/lib"
110
diff --git a/.github/workflows/vtest.yml b/.github/workflows/vtest.yml
index ea39662..781a2b3 100644
--- a/.github/workflows/vtest.yml
+++ b/.github/workflows/vtest.yml
@@ -50,7 +50,7 @@ jobs:
50 - name: Generate cache key50 - name: Generate cache key
51 id: generate-cache-key51 id: generate-cache-key
52 run: |52 run: |
53 echo "::set-output name=key::$(echo ${{ matrix.name }} | sha256sum | awk '{print $1}')"53 echo "key=$(echo ${{ matrix.name }} | sha256sum | awk '{print $1}')" >> $GITHUB_OUTPUT
5454
55 - name: Cache SSL libs55 - name: Cache SSL libs
56 if: ${{ matrix.ssl && matrix.ssl != 'stock' && matrix.ssl != 'BORINGSSL=yes' && matrix.ssl != 'QUICTLS=yes' }}56 if: ${{ matrix.ssl && matrix.ssl != 'stock' && matrix.ssl != 'BORINGSSL=yes' && matrix.ssl != 'QUICTLS=yes' }}
@@ -114,6 +114,9 @@ jobs:
114 run: make -C addons/wurfl/dummy114 run: make -C addons/wurfl/dummy
115 - name: Compile HAProxy with ${{ matrix.CC }}115 - name: Compile HAProxy with ${{ matrix.CC }}
116 run: |116 run: |
117 echo "::group::Show compiler's version"
118 echo | ${{ matrix.CC }} -v
119 echo "::endgroup::"
117 echo "::group::Show platform specific defines"120 echo "::group::Show platform specific defines"
118 echo | ${{ matrix.CC }} -dM -xc -E -121 echo | ${{ matrix.CC }} -dM -xc -E -
119 echo "::endgroup::"122 echo "::endgroup::"
@@ -138,7 +141,7 @@ jobs:
138 fi141 fi
139 echo "::endgroup::"142 echo "::endgroup::"
140 haproxy -vv143 haproxy -vv
141 echo "::set-output name=version::$(haproxy -v |awk 'NR==1{print $3}')"144 echo "version=$(haproxy -v |awk 'NR==1{print $3}')" >> $GITHUB_OUTPUT
142 - name: Install problem matcher for VTest145 - name: Install problem matcher for VTest
143 # This allows one to more easily see which tests fail.146 # This allows one to more easily see which tests fail.
144 run: echo "::add-matcher::.github/vtest.json"147 run: echo "::add-matcher::.github/vtest.json"
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index 58283ff..022c7f6 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -56,9 +56,10 @@ jobs:
56 TARGET=${{ matrix.TARGET }} \56 TARGET=${{ matrix.TARGET }} \
57 CC=${{ matrix.CC }} \57 CC=${{ matrix.CC }} \
58 DEBUG="-DDEBUG_STRICT -DDEBUG_MEMORY_POOLS -DDEBUG_POOL_INTEGRITY" \58 DEBUG="-DDEBUG_STRICT -DDEBUG_MEMORY_POOLS -DDEBUG_POOL_INTEGRITY" \
59 DEBUG_CFLAGS="-g -Wno-deprecated-declarations" \
59 ${{ join(matrix.FLAGS, ' ') }}60 ${{ join(matrix.FLAGS, ' ') }}
60 - name: Show HAProxy version61 - name: Show HAProxy version
61 id: show-version62 id: show-version
62 run: |63 run: |
63 ./haproxy -vv64 ./haproxy -vv
64 echo "::set-output name=version::$(./haproxy -v |awk 'NR==1{print $3}')"65 echo "version=$(./haproxy -v |awk 'NR==1{print $3}')" >> $GITHUB_OUTPUT
diff --git a/CHANGELOG b/CHANGELOG
index f9eec74..d59309f 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,196 @@
1ChangeLog :1ChangeLog :
2===========2===========
33
42023/02/14 : 2.4.22
5 - BUG/MINOR: fcgi-app: prevent 'use-fcgi-app' in default section
6 - BUG/MEDIUM: ssl: wrong eviction from the session cache tree
7 - BUG/MINOR: ssl/crt-list: warn when a line is malformated
8 - BUG/MEDIUM: stick-table: do not leave entries in end of window during purge
9 - BUG/MEDIUM: cache: use the correct time reference when comparing dates
10 - DOC: config: fix option spop-check proxy compatibility
11 - DOC: config: 'http-send-name-header' option may be used in default section
12 - DOC: proxy-protocol: fix wrong byte in provided example
13 - BUG/MEDIUM: stconn: Schedule a shutw on shutr if data must be sent first
14 - CI: github: don't warn on deprecated openssl functions on windows
15 - BUG/CRITICAL: http: properly reject empty http header field names
16
172023/01/27 : 2.4.21
18 - BUG/MINOR: http-htx: Don't consider an URI as normalized after a set-uri action
19 - BUG/MEDIIM: stconn: Flush output data before forwarding close to write side
20 - CI: github: change "ubuntu-latest" to "ubuntu-20.04"
21 - BUILD: peers: peers-t.h depends on stick-table-t.h
22 - BUG/MINOR: resolvers: Don't wait periodic resolution on healthcheck failure
23 - BUG/MEDIUM: ssl: Verify error codes can exceed 63
24 - BUG/MINOR: ssl: Fix potential overflow
25 - BUG/MEDIUM: mworker: fix segv in early failure of mworker mode with peers
26 - BUG/MINOR: promex: create haproxy_backend_agg_server_status
27 - MINOR: promex: introduce haproxy_backend_agg_check_status
28 - DOC: promex: Add missing backend metrics
29 - BUG/MAJOR: fcgi: Fix uninitialized reserved bytes
30 - REGTESTS: fix the race conditions in iff.vtc
31 - REGTESTS: startup: check maxconn computation
32 - BUG/MEDIUM: resolvers: Use tick_first() to update the resolvers task timeout
33 - LICENSE: wurfl: clarify the dummy library license.
34 - BUG/MINOR: ssl: Fix memory leak of find_chain in ssl_sock_load_cert_chain
35 - BUG/MEDIUM: mux-h2: Refuse interim responses with end-stream flag set
36 - BUG/MINOR: pool/stats: Use ullong to report total pool usage in bytes in stats
37 - BUILD: makefile: build the features list dynamically
38 - BUILD: makefile: sort the features list
39 - BUG/MINOR: http-fetch: Only fill txn status during prefetch if not already set
40 - BUG/MAJOR: buf: Fix copy of wrapping output data when a buffer is realigned
41 - REGTEST: fix the race conditions in json_query.vtc
42 - REGTEST: fix the race conditions in digest.vtc
43 - REGTEST: fix the race conditions in hmac.vtc
44 - BUG/MINOR: http: Memory leak of http redirect rules' format string
45 - CLEANUP: htx: fix a typo in an error message of http_str_to_htx
46 - BUG/MINOR: h1-htx: Remove flags about protocol upgrade on non-101 responses
47 - BUG/MINOR: resolvers: Wait the resolution execution for a do_resolv action
48 - BUG/MINOR: promex: Don't forget to consume the request on error
49 - BUG/MINOR: http-ana: Report SF_FINST_R flag on error waiting the request body
50 - BUG/MINOR: http-fetch: Don't block HTTP sample fetch eval in HTTP_MSG_ERROR state
51 - BUG/MINOR: http-ana: make set-status also update txn->status
52 - BUG/MINOR: listeners: fix suspend/resume of inherited FDs
53 - DOC: config: fix wrong section number for "protocol prefixes"
54 - DOC: config: fix aliases for protocol prefixes "udp4@" and "udp6@"
55 - BUG/MINOR: mux-fcgi: Correctly set pathinfo
56 - DOC: config: fix "Address formats" chapter syntax
57 - BUG/MINOR: listener: close tiny race between resume_listener() and stopping
58 - BUG/MINOR: mux-h2: add missing traces on failed headers decoding
59 - BUILD: hpack: include global.h for the trash that is needed in debug mode
60 - BUG/MINOR: sink: free the forwarding task on exit
61
622022/12/09 : 2.4.20
63 - BUG/MINOR: checks: update pgsql regex on auth packet
64 - DOC: config: Fix pgsql-check documentation to make user param mandatory
65 - BUG/MEDIUM: lua: Don't crash in hlua_lua2arg_check on failure
66 - BUG/MEDIUM: lua: handle stick table implicit arguments right.
67 - BUILD: h1: silence an initiialized warning with gcc-4.7 and -Os
68 - BUG/MINOR: http-fetch: Update method after a prefetch in smp_fetch_meth()
69 - BUILD: http_fetch: silence an uninitiialized warning with gcc-4/5/6 at -Os
70 - BUG/MINOR: mux-h1: Account consumed output data on synchronous connection error
71 - MINOR: smtpchk: Update expect rule to fully match replies to EHLO commands
72 - BUG/MINOR: smtpchk: SMTP Service check should gracefully close SMTP transaction
73 - BUG/MINOR: backend: only enforce turn-around state when not redispatching
74 - DOC: configuration: missing 'if' in tcp-request content example
75 - BUG/MAJOR: stick-tables: do not try to index a server name for applets
76 - BUG/MINOR: server: make sure "show servers state" hides private bits
77 - CI: Replace the deprecated `::set-output` command by writing to $GITHUB_OUTPUT in matrix.py
78 - CI: Replace the deprecated `::set-output` command by writing to $GITHUB_OUTPUT in workflow definition
79 - BUG/MINOR: log: Preserve message facility when the log target is a ring buffer
80 - BUG/MINOR: ring: Properly parse connect timeout
81 - BUG/MEDIUM: compression: handle rewrite errors when updating response headers
82 - BUG/MINOR: sink: Only use backend capability for the sink proxies
83 - BUG/MINOR: sink: Set default connect/server timeout for implicit ring buffers
84 - CI: SSL: use proper version generating when "latest" semantic is used
85 - CI: SSL: temporarily stick to LibreSSL=3.5.3
86 - BUG/MINOR: stick-table: Use server_id instead of std_t_sint in process_store_rules()
87 - DOC: management: add forgotten "show startup-logs"
88 - BUG/MAJOR: stick-table: don't process store-response rules for applets
89 - BUG/MEDIUM: stick-table: fix a race condition when updating the expiration task
90 - BUG/MINOR: log: fixing bug in tcp syslog_io_handler Octet-Counting
91 - CI: add monthly gcc cross compile jobs
92 - BUG/MINOR: ssl: Memory leak of AUTHORITY_KEYID struct when loading issuer
93 - BUG/MINOR: ssl: ocsp structure not freed properly in case of error
94 - CI: switch to the "latest" LibreSSL
95 - CI: emit the compiler's version in the build reports
96 - BUG/MEDIUM: wdt/clock: properly handle early task hangs
97 - BUG/MINOR: http-htx: Fix error handling during parsing http replies
98 - BUG/MINOR: resolvers: Set port before IP address when processing SRV records
99 - BUG/MINOR: mux-fcgi: Be sure to send empty STDING record in case of zero-copy
100 - BUG/MEDIUM: mux-fcgi: Avoid value length overflow when it doesn't fit at once
101 - BUG/MINOR: mux-h1: Do not send a last null chunk on body-less answers
102 - REG-TESTS: cache: Remove T-E header for 304-Not-Modified responses
103 - DOC: config: fix alphabetical ordering of global section
104 - BUG/MEDIUM: ring: fix creation of server in uninitialized ring
105 - BUG/MINOR: pool/cli: use ullong to report total pool usage in bytes
106 - BUG/MEDIUM: listener: Fix race condition when updating the global mngmt task
107 - BUG/MINOR: http_ana/txn: don't re-initialize txn and req var lists
108 - BUG/MINOR: ssl: don't initialize the keylog callback when not required
109 - BUG/MEDIUM: peers: messages about unkown tables not correctly ignored
110 - BUILD: peers: Remove unused variables
111 - BUG/MINOR: server/idle: at least use atomic stores when updating max_used_conns
112 - BUILD: listener: fix build warning on global_listener_rwlock without threads
113 - BUG/MINOR: cfgparse-listen: fix ebpt_next_dup pointer dereference on proxy "from" inheritance
114 - BUG/MINOR: log: fix parse_log_message rfc5424 size check
115 - BUG/MINOR: http-htx: Don't consider an URI as normalized after a set-uri action
116 - BUILD: http-htx: Silent build error about a possible NULL start-line
117 - BUG/MINOR: mux-h1: Fix handling of 408-Request-Time-Out
118 - Revert "BUG/MINOR: http-htx: Don't consider an URI as normalized after a set-uri action"
119 - DOC: config: provide some configuration hints for "http-reuse"
120 - DOC: config: clarify the fact that SNI should not be used in HTTP scenarios
121 - DOC: config: mention that a single monitor-uri rule is supported
122 - DOC: config: explain how default matching method for ACL works
123 - DOC: config: clarify the fact that "retries" is not just for connections
124 - DOC: config: clarify the -m dir and -m dom pattern matching methods
125 - SCRIPTS: announce-release: add a link to the data plane API
126 - Revert "CI: switch to the "latest" LibreSSL"
127 - Revert "CI: determine actual OpenSSL version dynamically"
128
1292022/09/28 : 2.4.19
130 - BUG/MEDIUM: mworker: use default maxconn in wait mode
131 - MINOR: http: Add function to get port part of a host
132 - MINOR: http: Add function to detect default port
133 - BUG/MEDIUM: h1: Improve authority validation for CONNCET request
134 - MINOR: http-htx: Use new HTTP functions for the scheme based normalization
135 - MINOR: ebtree: add ebmb_lookup_shorter() to pursue lookups
136 - BUG/MEDIUM: pattern: only visit equivalent nodes when skipping versions
137 - MINOR: peers: Use a dedicated reconnect timeout when stopping the local peer
138 - BUG/MEDIUM: peers: limit reconnect attempts of the old process on reload
139 - BUG/MINOR: peers: Use right channel flag to consider the peer as connected
140 - BUG/MEDIUM: dns: Properly initialize new DNS session
141 - MINOR: server: Constify source server to copy its settings
142 - REORG: server: Export srv_settings_cpy() function
143 - BUG/MEDIUM: proxy: Perform a custom copy for default server settings
144 - BUG/MINOR: ring/cli: fix a race condition between the writer and the reader
145 - BUG/MINOR: sink: fix a race condition between the writer and the reader
146 - BUILD: cfgparse: always defined _GNU_SOURCE for sched.h and crypt.h
147 - BUG/MEDIUM: poller: use fd_delete() to release the poller pipes
148 - BUG/MEDIUM: task: relax one thread consistency check in task_unlink_wq()
149 - BUILD: debug: silence warning on gcc-5
150 - BUG/MEDIUM: ring: fix too lax 'size' parser
151 - BUILD: http: silence an uninitialized warning affecting gcc-5
152 - BUG/MEDIUM: http-ana: fix crash or wrong header deletion by http-restrict-req-hdr-names
153 - BUG/MEDIUM: mux-h2: do not fiddle with ->dsi to indicate demux is idle
154 - BUG/MAJOR: log-forward: Fix log-forward proxies not fully initialized
155 - BUG/MAJOR: mworker: fix infinite loop on master with no proxies.
156 - BUG/MINOR: resolvers: return the correct value in resolvers_finalize_config()
157 - BUG/MINOR: tcpcheck: Disable QUICKACK only if data should be sent after connect
158 - REGTESTS: Fix prometheus script to perform HTTP health-checks
159 - DOC: configuration: do-resolve doesn't work with a port in the string
160 - BUG/MEDIUM: spoe: Properly update streams waiting for a ACK in async mode
161 - BUG/MEDIUM: peers: Add connect and server timeut to peers proxy
162 - BUG/MEDIUM: peers: Don't use resync timer when local resync is in progress
163 - BUG/MEDIUM: peers: Don't start resync on reload if local peer is not up-to-date
164 - BUG/MINOR: hlua: Rely on CF_EOI to detect end of message in HTTP applets
165 - BUG/MINOR: tcpcheck: Disable QUICKACK for default tcp-check (with no rule)
166 - BUG/MEDIUM: mux-h1: do not refrain from signaling errors after end of input
167 - REGTESTS: http_request_buffer: Add a barrier to not mix up log messages
168 - BUG/MEDIUM: mux-h1: always use RST to kill idle connections in pools
169 - BUG/MINOR: mux-h2: fix the "show fd" dest buffer for the subscriber
170 - BUG/MINOR: mux-h1: fix the "show fd" dest buffer for the subscriber
171 - BUG/MINOR: mux-fcgi: fix the "show fd" dest buffer for the subscriber
172 - BUG/MINOR: regex: Properly handle PCRE2 lib compiled without JIT support
173 - BUILD: makefile: enable crypt(3) for NetBSD
174 - BUG/MINOR: h1: Support headers case adjustment for TCP proxies
175 - BUG/MINOR: task: always reset a new tasklet's call date
176 - BUG/MINOR: signals/poller: set the poller timeout to 0 when there are signals
177 - BUG/MINOR: signals/poller: ensure wakeup from signals
178 - CI: cirrus-ci: bump FreeBSD image to 13-1
179 - BUG/MEDIUM: proxy: ensure pause_proxy() and resume_proxy() own PROXY_LOCK
180 - MINOR: listener: small API change
181 - BUG/MINOR: stats: fixing stat shows disabled frontend status as 'OPEN'
182 - REGTESTS: healthcheckmail: Relax matching on the healthcheck log message
183 - REGTESTS: log: test the log-forward feature
184 - BUG/MEDIUM: sink: bad init sequence on tcp sink from a ring.
185 - REGTESTS: ssl/log: test the log-forward with SSL
186 - DOC: fix TOC in starter guide for subsection 3.3.8. Statistics
187 - BUG/MEDIUM: captures: free() an error capture out of the proxy lock
188 - BUILD: fd: fix a build warning on the DWCAS
189 - SCRIPTS: announce-release: update some URLs to https
190 - BUG/MINOR: log: improper behavior when escaping log data
191 - REGTESTS: 4be_1srv_smtpchk_httpchk_layer47errors: Return valid SMTP replies
192 - BUG/MEDIUM: resolvers: Remove aborted resolutions from query_ids tree
193
42022/07/27 : 2.4.181942022/07/27 : 2.4.18
5 - CI: determine actual LibreSSL version dynamically195 - CI: determine actual LibreSSL version dynamically
6 - MEDIUM: http-ana: Add a proxy option to restrict chars in request header names196 - MEDIUM: http-ana: Add a proxy option to restrict chars in request header names
diff --git a/Makefile b/Makefile
index c0a6a27..40c2b10 100644
--- a/Makefile
+++ b/Makefile
@@ -423,8 +423,8 @@ endif
423# NetBSD 8 and above423# NetBSD 8 and above
424ifeq ($(TARGET),netbsd)424ifeq ($(TARGET),netbsd)
425 set_target_defaults = $(call default_opts, \425 set_target_defaults = $(call default_opts, \
426 USE_POLL USE_TPROXY USE_THREAD USE_KQUEUE USE_ACCEPT4 USE_CLOSEFROM \426 USE_POLL USE_TPROXY USE_LIBCRYPT USE_THREAD USE_KQUEUE USE_ACCEPT4 \
427 USE_GETADDRINFO)427 USE_CLOSEFROM USE_GETADDRINFO)
428endif428endif
429429
430# AIX 5.1 only430# AIX 5.1 only
@@ -524,7 +524,11 @@ ignore_implicit = $(if $(subst environment,,$(origin $(1))), \
524# is used to report a list of all flags which were used to build this version.524# is used to report a list of all flags which were used to build this version.
525# Do not assign anything to it.525# Do not assign anything to it.
526BUILD_OPTIONS := $(foreach opt,$(use_opts),$(call ignore_implicit,$(opt)))526BUILD_OPTIONS := $(foreach opt,$(use_opts),$(call ignore_implicit,$(opt)))
527BUILD_FEATURES := $(foreach opt,$(patsubst USE_%,%,$(use_opts)),$(if $(USE_$(opt)),+$(opt),-$(opt)))527
528# Make a list of all known features with +/- prepended depending on their
529# activation status. Must be a macro so that dynamically enabled ones are
530# evaluated with their current status.
531BUILD_FEATURES = $(foreach opt,$(patsubst USE_%,%,$(sort $(use_opts))),$(if $(USE_$(opt)),+$(opt),-$(opt)))
528532
529# All USE_* options have their equivalent macro defined in the code (some might533# All USE_* options have their equivalent macro defined in the code (some might
530# possibly be unused though)534# possibly be unused though)
diff --git a/SUBVERS b/SUBVERS
index 994ee02..f042fd0 100644
--- a/SUBVERS
+++ b/SUBVERS
@@ -1,2 +1,2 @@
1-1d80f181-f8e3218
22
diff --git a/VERDATE b/VERDATE
index 6a4d254..d8a3372 100644
--- a/VERDATE
+++ b/VERDATE
@@ -1,2 +1,2 @@
12022-07-27 15:10:44 +020012023-02-14 16:57:13 +0100
22022/07/2722023/02/14
diff --git a/VERSION b/VERSION
index cc2ff5a..76cb51e 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
12.4.1812.4.22
diff --git a/addons/promex/README b/addons/promex/README
index e41ebdc..4e29e23 100644
--- a/addons/promex/README
+++ b/addons/promex/README
@@ -286,6 +286,8 @@ See prometheus export for the description of each field.
286| haproxy_backend_max_total_time_seconds |286| haproxy_backend_max_total_time_seconds |
287| haproxy_backend_internal_errors_total |287| haproxy_backend_internal_errors_total |
288| haproxy_backend_uweight |288| haproxy_backend_uweight |
289| haproxy_backend_agg_server_status |
290| haproxy_backend_agg_check_status |
289+-----------------------------------------------------+291+-----------------------------------------------------+
290292
291* Server metrics293* Server metrics
diff --git a/addons/promex/service-prometheus.c b/addons/promex/service-prometheus.c
index b267f98..d31b666 100644
--- a/addons/promex/service-prometheus.c
+++ b/addons/promex/service-prometheus.c
@@ -289,6 +289,8 @@ const struct promex_metric promex_st_metrics[ST_F_TOTAL_FIELDS] = {
289 [ST_F_NEED_CONN_EST] = { .n = IST("need_connections_current"), .type = PROMEX_MT_GAUGE, .flags = ( PROMEX_FL_SRV_METRIC) },289 [ST_F_NEED_CONN_EST] = { .n = IST("need_connections_current"), .type = PROMEX_MT_GAUGE, .flags = ( PROMEX_FL_SRV_METRIC) },
290 [ST_F_UWEIGHT] = { .n = IST("uweight"), .type = PROMEX_MT_GAUGE, .flags = ( PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },290 [ST_F_UWEIGHT] = { .n = IST("uweight"), .type = PROMEX_MT_GAUGE, .flags = ( PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },
291 [ST_F_AGG_SRV_CHECK_STATUS] = { .n = IST("agg_server_check_status"), .type = PROMEX_MT_GAUGE, .flags = ( PROMEX_FL_BACK_METRIC ) },291 [ST_F_AGG_SRV_CHECK_STATUS] = { .n = IST("agg_server_check_status"), .type = PROMEX_MT_GAUGE, .flags = ( PROMEX_FL_BACK_METRIC ) },
292 [ST_F_AGG_SRV_STATUS ] = { .n = IST("agg_server_status"), .type = PROMEX_MT_GAUGE, .flags = ( PROMEX_FL_BACK_METRIC ) },
293 [ST_F_AGG_CHECK_STATUS] = { .n = IST("agg_check_status"), .type = PROMEX_MT_GAUGE, .flags = ( PROMEX_FL_BACK_METRIC ) },
292};294};
293295
294/* Description of overridden stats fields */296/* Description of overridden stats fields */
@@ -792,6 +794,7 @@ static int promex_dump_back_metrics(struct appctx *appctx, struct htx *htx)
792 double secs;794 double secs;
793 enum promex_back_state bkd_state;795 enum promex_back_state bkd_state;
794 enum promex_srv_state srv_state;796 enum promex_srv_state srv_state;
797 enum healthcheck_status srv_check_status;
795798
796 for (;appctx->st2 < ST_F_TOTAL_FIELDS; appctx->st2++) {799 for (;appctx->st2 < ST_F_TOTAL_FIELDS; appctx->st2++) {
797 if (!(promex_st_metrics[appctx->st2].flags & appctx->ctx.stats.flags))800 if (!(promex_st_metrics[appctx->st2].flags & appctx->ctx.stats.flags))
@@ -800,6 +803,8 @@ static int promex_dump_back_metrics(struct appctx *appctx, struct htx *htx)
800 while (appctx->ctx.stats.obj1) {803 while (appctx->ctx.stats.obj1) {
801 struct promex_label labels[PROMEX_MAX_LABELS-1] = {};804 struct promex_label labels[PROMEX_MAX_LABELS-1] = {};
802 unsigned int srv_state_count[PROMEX_SRV_STATE_COUNT] = { 0 };805 unsigned int srv_state_count[PROMEX_SRV_STATE_COUNT] = { 0 };
806 unsigned int srv_check_count[HCHK_STATUS_SIZE] = { 0 };
807 const char *check_state;
803808
804 px = appctx->ctx.stats.obj1;809 px = appctx->ctx.stats.obj1;
805810
@@ -814,7 +819,8 @@ static int promex_dump_back_metrics(struct appctx *appctx, struct htx *htx)
814 return -1;819 return -1;
815820
816 switch (appctx->st2) {821 switch (appctx->st2) {
817 case ST_F_AGG_SRV_CHECK_STATUS:822 case ST_F_AGG_SRV_CHECK_STATUS: // DEPRECATED
823 case ST_F_AGG_SRV_STATUS:
818 if (!px->srv)824 if (!px->srv)
819 goto next_px;825 goto next_px;
820 sv = px->srv;826 sv = px->srv;
@@ -833,6 +839,28 @@ static int promex_dump_back_metrics(struct appctx *appctx, struct htx *htx)
833 }839 }
834 appctx->ctx.stats.st_code = 0;840 appctx->ctx.stats.st_code = 0;
835 goto next_px;841 goto next_px;
842 case ST_F_AGG_CHECK_STATUS:
843 if (!px->srv)
844 goto next_px;
845 sv = px->srv;
846 while (sv) {
847 srv_check_status = sv->check.status;
848 srv_check_count[srv_check_status] += 1;
849 sv = sv->next;
850 }
851 for (; appctx->ctx.stats.st_code < HCHK_STATUS_SIZE; appctx->ctx.stats.st_code++) {
852 if (get_check_status_result(appctx->ctx.stats.st_code) < CHK_RES_FAILED)
853 continue;
854 val = mkf_u32(FO_STATUS, srv_check_count[appctx->ctx.stats.st_code]);
855 check_state = get_check_status_info(appctx->ctx.stats.st_code);
856 labels[1].name = ist("state");
857 labels[1].value = ist(check_state);
858 if (!promex_dump_metric(appctx, htx, prefix, &promex_st_metrics[appctx->st2],
859 &val, labels, &out, max))
860 goto full;
861 }
862 appctx->ctx.stats.st_code = 0;
863 goto next_px;
836 case ST_F_STATUS:864 case ST_F_STATUS:
837 bkd_state = ((px->lbprm.tot_weight > 0 || !px->srv) ? 1 : 0);865 bkd_state = ((px->lbprm.tot_weight > 0 || !px->srv) ? 1 : 0);
838 for (; appctx->ctx.stats.st_code < PROMEX_BACK_STATE_COUNT; appctx->ctx.stats.st_code++) {866 for (; appctx->ctx.stats.st_code < PROMEX_BACK_STATE_COUNT; appctx->ctx.stats.st_code++) {
@@ -1547,6 +1575,7 @@ static void promex_appctx_handle_io(struct appctx *appctx)
1547 res->flags |= CF_READ_NULL;1575 res->flags |= CF_READ_NULL;
1548 si_shutr(si);1576 si_shutr(si);
1549 si_shutw(si);1577 si_shutw(si);
1578 goto out;
1550}1579}
15511580
1552struct applet promex_applet = {1581struct applet promex_applet = {
diff --git a/addons/wurfl/dummy/wurfl/wurfl.h b/addons/wurfl/dummy/wurfl/wurfl.h
index 3b450fc..7659561 100644
--- a/addons/wurfl/dummy/wurfl/wurfl.h
+++ b/addons/wurfl/dummy/wurfl/wurfl.h
@@ -4,11 +4,16 @@
4 * Copyright (c) ScientiaMobile, Inc.4 * Copyright (c) ScientiaMobile, Inc.
5 * http://www.scientiamobile.com5 * http://www.scientiamobile.com
6 *6 *
7 * This software package is the property of ScientiaMobile Inc. and is licensed7 * This software package is the property of ScientiaMobile Inc. and is distributed under
8 * commercially according to a contract between the Licensee and ScientiaMobile Inc. (Licensor).8 * a dual licensing scheme:
9 * If you represent the Licensee, please refer to the licensing agreement which has been signed9 *
10 * between the two parties. If you do not represent the Licensee, you are not authorized to use10 * 1) commercially according to a contract between the Licensee and ScientiaMobile Inc. (Licensor).
11 * this software in any way.11 * If you represent the Licensee, please refer to the licensing agreement which has been signed
12 * between the two parties. If you do not represent the Licensee, you are not authorized to use
13 * this software in any way.
14 *
15 * 2) LGPL when used in the context of the HAProxy project with the purpose of testing compatibility
16 * of HAProxy with ScientiaMobile software.
12 *17 *
13 */18 */
1419
diff --git a/debian/changelog b/debian/changelog
index 02ccd97..ca7af92 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,23 @@
1haproxy (2.4.22-0ubuntu0.22.10.1) kinetic; urgency=medium
2
3 * New upstream release (LP: #2012557).
4 - Major and critical bug fixes according to the upstream changelog:
5 + BUG/MAJOR: log-forward: Fix log-forward proxies not fully initialized
6 + BUG/MAJOR: mworker: fix infinite loop on master with no proxies.
7 + BUG/MAJOR: stick-tables: do not try to index a server name for applets
8 + BUG/MAJOR: stick-table: don't process store-response rules for applets
9 + BUG/MAJOR: fcgi: Fix uninitialized reserved bytes
10 + BUG/MAJOR: buf: Fix copy of wrapping output data when a buffer is realigned
11 + BUG/CRITICAL: http: properly reject empty http header field names
12 - Remove patches applied by upstream in debian/patches:
13 + CVE-2023-0056.patch
14 + CVE-2023-25725.patch
15 + CVE-2023-0836.patch
16 - Refresh existing patches in debian/patches:
17 + reproducible.patch
18
19 -- Lucas Kanashiro <kanashiro@ubuntu.com> Wed, 22 Mar 2023 18:39:05 -0300
20
1haproxy (2.4.18-1ubuntu1.3) kinetic-security; urgency=medium21haproxy (2.4.18-1ubuntu1.3) kinetic-security; urgency=medium
222
3 * SECURITY UPDATE: information leak via uninitialized bytes23 * SECURITY UPDATE: information leak via uninitialized bytes
diff --git a/debian/patches/CVE-2023-0056.patch b/debian/patches/CVE-2023-0056.patch
4deleted file mode 10064424deleted file mode 100644
index dd8b02d..0000000
--- a/debian/patches/CVE-2023-0056.patch
+++ /dev/null
@@ -1,38 +0,0 @@
1From 827a6299e6995c5c3ba620d8b7cbacdaef67f2c4 Mon Sep 17 00:00:00 2001
2From: Christopher Faulet <cfaulet@haproxy.com>
3Date: Thu, 22 Dec 2022 09:47:01 +0100
4Subject: [PATCH] BUG/MEDIUM: mux-h2: Refuse interim responses with end-stream
5 flag set
6
7As state in RFC9113#8.1, HEADERS frame with the ES flag set that carries an
8informational status code is malformed. However, there is no test on this
9condition.
10
11On 2.4 and higher, it is hard to predict consequences of this bug because
12end of the message is only reported with a flag. But on 2.2 and lower, it
13leads to a crash because there is an unexpected extra EOM block at the end
14of an interim response.
15
16Now, when a ES flag is detected on a HEADERS frame for an interim message, a
17stream error is sent (RST_STREAM/PROTOCOL_ERROR).
18
19This patch should solve the issue #1972. It should be backported as far as
202.0.
21---
22 src/mux_h2.c | 5 +++++
23 1 file changed, 5 insertions(+)
24
25--- a/src/mux_h2.c
26+++ b/src/mux_h2.c
27@@ -4940,6 +4940,11 @@ next_frame:
28 *flags |= H2_SF_HEADERS_RCVD;
29
30 if (h2c->dff & H2_F_HEADERS_END_STREAM) {
31+ if (msgf & H2_MSGF_RSP_1XX) {
32+ /* RFC9113#8.1 : HEADERS frame with the ES flag set that carries an informational status code is malformed */
33+ TRACE_STATE("invalid interim response with ES flag!", H2_EV_RX_FRAME|H2_EV_RX_HDR|H2_EV_H2C_ERR|H2_EV_PROTO_ERR, h2c->conn);
34+ goto fail;
35+ }
36 /* no more data are expected for this message */
37 htx->flags |= HTX_FL_EOM;
38 }
diff --git a/debian/patches/CVE-2023-0836.patch b/debian/patches/CVE-2023-0836.patch
39deleted file mode 1006440deleted file mode 100644
index f708696..0000000
--- a/debian/patches/CVE-2023-0836.patch
+++ /dev/null
@@ -1,47 +0,0 @@
1From f988992d16f45ef03d5bbb024a1042ed8123e4c5 Mon Sep 17 00:00:00 2001
2From: Youfu Zhang <zhangyoufu@gmail.com>
3Date: Fri, 9 Dec 2022 19:15:48 +0800
4Subject: [PATCH] BUG/MAJOR: fcgi: Fix uninitialized reserved bytes
5
6The output buffer is not zero-initialized. If we don't clear reserved
7bytes, fcgi requests sent to backend will leak sensitive data.
8
9This patch must be backported as far as 2.2.
10
11(cherry picked from commit 2e6bf0a2722866ae0128a4392fa2375bd1f03ff8)
12Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
13(cherry picked from commit db03179fee55c60a92ce6b86a0f04dbb9ba0328b)
14Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
15---
16 src/fcgi.c | 8 ++++++--
17 1 file changed, 6 insertions(+), 2 deletions(-)
18
19diff --git a/src/fcgi.c b/src/fcgi.c
20index dcf2db2..1d1a82b 100644
21--- a/src/fcgi.c
22+++ b/src/fcgi.c
23@@ -47,7 +47,7 @@ int fcgi_encode_record_hdr(struct buffer *out, const struct fcgi_header *h)
24 out->area[len++] = ((h->len >> 8) & 0xff);
25 out->area[len++] = (h->len & 0xff);
26 out->area[len++] = h->padding;
27- len++; /* rsv */
28+ out->area[len++] = 0; /* rsv */
29
30 out->data = len;
31 return 1;
32@@ -94,7 +94,11 @@ int fcgi_encode_begin_request(struct buffer *out, const struct fcgi_begin_reques
33 out->area[len++] = ((r->role >> 8) & 0xff);
34 out->area[len++] = (r->role & 0xff);
35 out->area[len++] = r->flags;
36- len += 5; /* rsv */
37+ out->area[len++] = 0; /* rsv */
38+ out->area[len++] = 0;
39+ out->area[len++] = 0;
40+ out->area[len++] = 0;
41+ out->area[len++] = 0;
42
43 out->data = len;
44 return 1;
45--
461.7.10.4
47
diff --git a/debian/patches/CVE-2023-25725.patch b/debian/patches/CVE-2023-25725.patch
48deleted file mode 1006440deleted file mode 100644
index 1897223..0000000
--- a/debian/patches/CVE-2023-25725.patch
+++ /dev/null
@@ -1,145 +0,0 @@
1From a6c7ac9d51248a641f456906549120d3f6387049 Mon Sep 17 00:00:00 2001
2From: Willy Tarreau <w@1wt.eu>
3Date: Thu, 9 Feb 2023 21:36:54 +0100
4Subject: BUG/CRITICAL: http: properly reject empty http header field names
5
6The HTTP header parsers surprizingly accepts empty header field names,
7and this is a leftover from the original code that was agnostic to this.
8
9When muxes were introduced, for H2 first, the HPACK decompressor needed
10to feed headers lists, and since empty header names were strictly
11forbidden by the protocol, the lists of headers were purposely designed
12to be terminated by an empty header field name (a principle that is
13similar to H1's empty line termination). This principle was preserved
14and generalized to other protocols migrated to muxes (H1/FCGI/H3 etc)
15without anyone ever noticing that the H1 parser was still able to deliver
16empty header field names to this list. In addition to this it turns out
17that the HPACK decompressor, despite a comment in the code, may
18successfully decompress an empty header field name, and this mistake
19was propagated to the QPACK decompressor as well.
20
21The impact is that an empty header field name may be used to truncate
22the list of headers and thus make some headers disappear. While for
23H2/H3 the impact is limited as haproxy sees a request with missing
24headers, and headers are not used to delimit messages, in the case of
25HTTP/1, the impact is significant because the presence (and sometimes
26contents) of certain sensitive headers is detected during the parsing.
27Thus, some of these headers may be seen, marked as present, their value
28extracted, but never delivered to upper layers and obviously not
29forwarded to the other side either. This can have for consequence that
30certain important header fields such as Connection, Upgrade, Host,
31Content-length, Transfer-Encoding etc are possibly seen as different
32between what haproxy uses to parse/forward/route and what is observed
33in http-request rules and of course, forwarded. One direct consequence
34is that it is possible to exploit this property in HTTP/1 to make
35affected versions of haproxy forward more data than is advertised on
36the other side, and bypass some access controls or routing rules by
37crafting extraneous requests. Note, however, that responses to such
38requests will normally not be passed back to the client, but this can
39still cause some harm.
40
41This specific risk can be mostly worked around in configuration using
42the following rule that will rely on the bug's impact to precisely
43detect the inconsistency between the known body size and the one
44expected to be advertised to the server (the rule works from 2.0 to
452.8-dev):
46
47 http-request deny if { fc_http_major 1 } !{ req.body_size 0 } !{ req.hdr(content-length) -m found } !{ req.hdr(transfer-encoding) -m found } !{ method CONNECT }
48
49This will exclusively block such carefully crafted requests delivered
50over HTTP/1. HTTP/2 and HTTP/3 do not need content-length, and a body
51that arrives without being announced with a content-length will be
52forwarded using transfer-encoding, hence will not cause discrepancies.
53In HAProxy 2.0 in legacy mode ("no option http-use-htx"), this rule will
54simply have no effect but will not cause trouble either.
55
56A clean solution would consist in modifying the loops iterating over
57these headers lists to check the header name's pointer instead of its
58length (since both are zero at the end of the list), but this requires
59to touch tens of places and it's very easy to miss one. Functions such
60as htx_add_header(), htx_add_trailer(), htx_add_all_headers() would be
61good starting points for such a possible future change.
62
63Instead the current fix focuses on blocking empty headers where they
64are first inserted, hence in the H1/HPACK/QPACK decoders. One benefit
65of the current solution (for H1) is that it allows "show errors" to
66report a precise diagnostic when facing such invalid HTTP/1 requests,
67with the exact location of the problem and the originating address:
68
69 $ printf "GET / HTTP/1.1\r\nHost: localhost\r\n:empty header\r\n\r\n" | nc 0 8001
70 HTTP/1.1 400 Bad request
71 Content-length: 90
72 Cache-Control: no-cache
73 Connection: close
74 Content-Type: text/html
75
76 <html><body><h1>400 Bad request</h1>
77 Your browser sent an invalid request.
78 </body></html>
79
80 $ socat /var/run/haproxy.stat <<< "show errors"
81 Total events captured on [10/Feb/2023:16:29:37.530] : 1
82
83 [10/Feb/2023:16:29:34.155] frontend decrypt (#2): invalid request
84 backend <NONE> (#-1), server <NONE> (#-1), event #0, src 127.0.0.1:31092
85 buffer starts at 0 (including 0 out), 16334 free,
86 len 50, wraps at 16336, error at position 33
87 H1 connection flags 0x00000000, H1 stream flags 0x00000810
88 H1 msg state MSG_HDR_NAME(17), H1 msg flags 0x00001410
89 H1 chunk len 0 bytes, H1 body len 0 bytes :
90
91 00000 GET / HTTP/1.1\r\n
92 00016 Host: localhost\r\n
93 00033 :empty header\r\n
94 00048 \r\n
95
96I want to address sincere and warm thanks for their great work to the
97team composed of the following security researchers who found the issue
98together and reported it: Bahruz Jabiyev, Anthony Gavazzi, and Engin
99Kirda from Northeastern University, Kaan Onarlioglu from Akamai
100Technologies, Adi Peleg and Harvey Tuch from Google. And kudos to Amaury
101Denoyelle from HAProxy Technologies for spotting that the HPACK and
102QPACK decoders would let this pass despite the comment explicitly
103saying otherwise.
104
105This fix must be backported as far as 2.0. The QPACK changes can be
106dropped before 2.6. In 2.0 there is also the equivalent code for legacy
107mode, which doesn't suffer from the list truncation, but it would better
108be fixed regardless.
109---
110 src/h1.c | 4 ++++
111 src/hpack-dec.c | 9 +++++++++
112 src/qpack-dec.c | 9 +++++++++
113 3 files changed, 22 insertions(+)
114
115--- a/src/h1.c
116+++ b/src/h1.c
117@@ -706,6 +706,10 @@ int h1_headers_to_hdr_list(char *start,
118
119 if (likely(*ptr == ':')) {
120 col = ptr - start;
121+ if (col <= sol) {
122+ state = H1_MSG_HDR_NAME;
123+ goto http_msg_invalid;
124+ }
125 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_hdr_l1_sp, http_msg_ood, state, H1_MSG_HDR_L1_SP);
126 }
127
128--- a/src/hpack-dec.c
129+++ b/src/hpack-dec.c
130@@ -419,6 +419,15 @@ int hpack_decode_frame(struct hpack_dht
131 /* <name> and <value> are correctly filled here */
132 }
133
134+ /* We must not accept empty header names (forbidden by the spec and used
135+ * as a list termination).
136+ */
137+ if (!name.len) {
138+ hpack_debug_printf("##ERR@%d##\n", __LINE__);
139+ ret = -HPACK_ERR_INVALID_ARGUMENT;
140+ goto leave;
141+ }
142+
143 /* here's what we have here :
144 * - name.len > 0
145 * - value is filled with either const data or data allocated from tmp
diff --git a/debian/patches/reproducible.patch b/debian/patches/reproducible.patch
index bbc95b8..e499a79 100644
--- a/debian/patches/reproducible.patch
+++ b/debian/patches/reproducible.patch
@@ -1,8 +1,6 @@
1diff --git a/Makefile b/Makefile
2index 566bdb26a3e7..8603dea25c21 100644
3--- a/Makefile1--- a/Makefile
4+++ b/Makefile2+++ b/Makefile
5@@ -975,7 +975,7 @@ src/haproxy.o: src/haproxy.c $(DEP)3@@ -995,7 +995,7 @@
6 -DBUILD_ARCH='"$(strip $(ARCH))"' \4 -DBUILD_ARCH='"$(strip $(ARCH))"' \
7 -DBUILD_CPU='"$(strip $(CPU))"' \5 -DBUILD_CPU='"$(strip $(CPU))"' \
8 -DBUILD_CC='"$(strip $(CC))"' \6 -DBUILD_CC='"$(strip $(CC))"' \
diff --git a/debian/patches/series b/debian/patches/series
index 25260a8..276b0d5 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -4,6 +4,3 @@ haproxy.service-add-documentation.patch
4# applied during the build process:4# applied during the build process:
5# debianize-dconv.patch5# debianize-dconv.patch
6reproducible.patch6reproducible.patch
7CVE-2023-0056.patch
8CVE-2023-25725.patch
9CVE-2023-0836.patch
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 5d4c052..0c23dd1 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -3,7 +3,7 @@
3 Configuration Manual3 Configuration Manual
4 ----------------------4 ----------------------
5 version 2.45 version 2.4
6 2022/07/276 2023/02/14
77
88
9This document covers the configuration language as implemented in the version9This document covers the configuration language as implemented in the version
@@ -965,32 +965,36 @@ of them have command-line equivalents.
965The following keywords are supported in the "global" section :965The following keywords are supported in the "global" section :
966966
967 * Process management and security967 * Process management and security
968 - 51degrees-cache-size
969 - 51degrees-data-file
970 - 51degrees-property-name-list
971 - 51degrees-property-separator
968 - ca-base972 - ca-base
969 - chroot973 - chroot
970 - crt-base
971 - cpu-map974 - cpu-map
975 - crt-base
972 - daemon976 - daemon
973 - default-path977 - default-path
974 - description978 - description
975 - deviceatlas-json-file979 - deviceatlas-json-file
976 - deviceatlas-log-level980 - deviceatlas-log-level
977 - deviceatlas-separator
978 - deviceatlas-properties-cookie981 - deviceatlas-properties-cookie
982 - deviceatlas-separator
979 - expose-experimental-directives983 - expose-experimental-directives
980 - external-check984 - external-check
981 - gid985 - gid
982 - group986 - group
983 - hard-stop-after
984 - h1-case-adjust987 - h1-case-adjust
985 - h1-case-adjust-file988 - h1-case-adjust-file
989 - h2-workaround-bogus-websocket-clients
990 - hard-stop-after
986 - insecure-fork-wanted991 - insecure-fork-wanted
987 - insecure-setuid-wanted992 - insecure-setuid-wanted
988 - issuers-chain-path993 - issuers-chain-path
989 - h2-workaround-bogus-websocket-clients
990 - localpeer994 - localpeer
991 - log995 - log
992 - log-tag
993 - log-send-hostname996 - log-send-hostname
997 - log-tag
994 - lua-load998 - lua-load
995 - lua-load-per-thread999 - lua-load-per-thread
996 - lua-prepend-path1000 - lua-prepend-path
@@ -1003,13 +1007,9 @@ The following keywords are supported in the "global" section :
1003 - pp2-never-send-local1007 - pp2-never-send-local
1004 - presetenv1008 - presetenv
1005 - resetenv1009 - resetenv
1006 - uid
1007 - ulimit-n
1008 - user
1009 - set-dumpable1010 - set-dumpable
1010 - set-var1011 - set-var
1011 - setenv1012 - setenv
1012 - stats
1013 - ssl-default-bind-ciphers1013 - ssl-default-bind-ciphers
1014 - ssl-default-bind-ciphersuites1014 - ssl-default-bind-ciphersuites
1015 - ssl-default-bind-curves1015 - ssl-default-bind-curves
@@ -1020,25 +1020,25 @@ The following keywords are supported in the "global" section :
1020 - ssl-dh-param-file1020 - ssl-dh-param-file
1021 - ssl-server-verify1021 - ssl-server-verify
1022 - ssl-skip-self-issued-ca1022 - ssl-skip-self-issued-ca
1023 - stats
1024 - strict-limits
1025 - uid
1026 - ulimit-n
1023 - unix-bind1027 - unix-bind
1024 - unsetenv1028 - unsetenv
1025 - 51degrees-data-file1029 - user
1026 - 51degrees-property-name-list1030 - wurfl-cache-size
1027 - 51degrees-property-separator
1028 - 51degrees-cache-size
1029 - wurfl-data-file1031 - wurfl-data-file
1030 - wurfl-information-list1032 - wurfl-information-list
1031 - wurfl-information-list-separator1033 - wurfl-information-list-separator
1032 - wurfl-cache-size
1033 - strict-limits
10341034
1035 * Performance tuning1035 * Performance tuning
1036 - busy-polling1036 - busy-polling
1037 - max-spread-checks1037 - max-spread-checks
1038 - maxcompcpuusage
1039 - maxcomprate
1038 - maxconn1040 - maxconn
1039 - maxconnrate1041 - maxconnrate
1040 - maxcomprate
1041 - maxcompcpuusage
1042 - maxpipes1042 - maxpipes
1043 - maxsessrate1043 - maxsessrate
1044 - maxsslconn1044 - maxsslconn
@@ -1046,16 +1046,16 @@ The following keywords are supported in the "global" section :
1046 - maxzlibmem1046 - maxzlibmem
1047 - no-memory-trimming1047 - no-memory-trimming
1048 - noepoll1048 - noepoll
1049 - nokqueue
1050 - noevports1049 - noevports
1051 - nopoll
1052 - nosplice
1053 - nogetaddrinfo1050 - nogetaddrinfo
1051 - nokqueue
1052 - nopoll
1054 - noreuseport1053 - noreuseport
1054 - nosplice
1055 - profiling.tasks1055 - profiling.tasks
1056 - spread-checks
1057 - server-state-base1056 - server-state-base
1058 - server-state-file1057 - server-state-file
1058 - spread-checks
1059 - ssl-engine1059 - ssl-engine
1060 - ssl-mode-async1060 - ssl-mode-async
1061 - tune.buffers.limit1061 - tune.buffers.limit
@@ -1074,9 +1074,9 @@ The following keywords are supported in the "global" section :
1074 - tune.idletimer1074 - tune.idletimer
1075 - tune.lua.forced-yield1075 - tune.lua.forced-yield
1076 - tune.lua.maxmem1076 - tune.lua.maxmem
1077 - tune.lua.service-timeout
1077 - tune.lua.session-timeout1078 - tune.lua.session-timeout
1078 - tune.lua.task-timeout1079 - tune.lua.task-timeout
1079 - tune.lua.service-timeout
1080 - tune.maxaccept1080 - tune.maxaccept
1081 - tune.maxpollevents1081 - tune.maxpollevents
1082 - tune.maxrewrite1082 - tune.maxrewrite
@@ -1092,13 +1092,13 @@ The following keywords are supported in the "global" section :
1092 - tune.sndbuf.client1092 - tune.sndbuf.client
1093 - tune.sndbuf.server1093 - tune.sndbuf.server
1094 - tune.ssl.cachesize1094 - tune.ssl.cachesize
1095 - tune.ssl.capture-cipherlist-size
1096 - tune.ssl.default-dh-param
1097 - tune.ssl.force-private-cache
1095 - tune.ssl.keylog1098 - tune.ssl.keylog
1096 - tune.ssl.lifetime1099 - tune.ssl.lifetime
1097 - tune.ssl.force-private-cache
1098 - tune.ssl.maxrecord1100 - tune.ssl.maxrecord
1099 - tune.ssl.default-dh-param
1100 - tune.ssl.ssl-ctx-cache-size1101 - tune.ssl.ssl-ctx-cache-size
1101 - tune.ssl.capture-cipherlist-size
1102 - tune.vars.global-max-size1102 - tune.vars.global-max-size
1103 - tune.vars.proc-max-size1103 - tune.vars.proc-max-size
1104 - tune.vars.reqres-max-size1104 - tune.vars.reqres-max-size
@@ -1115,6 +1115,36 @@ The following keywords are supported in the "global" section :
11153.1. Process management and security11153.1. Process management and security
1116------------------------------------1116------------------------------------
11171117
111851degrees-data-file <file path>
1119 The path of the 51Degrees data file to provide device detection services. The
1120 file should be unzipped and accessible by HAProxy with relevant permissions.
1121
1122 Please note that this option is only available when HAProxy has been
1123 compiled with USE_51DEGREES.
1124
112551degrees-property-name-list [<string> ...]
1126 A list of 51Degrees property names to be load from the dataset. A full list
1127 of names is available on the 51Degrees website:
1128 https://51degrees.com/resources/property-dictionary
1129
1130 Please note that this option is only available when HAProxy has been
1131 compiled with USE_51DEGREES.
1132
113351degrees-property-separator <char>
1134 A char that will be appended to every property value in a response header
1135 containing 51Degrees results. If not set that will be set as ','.
1136
1137 Please note that this option is only available when HAProxy has been
1138 compiled with USE_51DEGREES.
1139
114051degrees-cache-size <number>
1141 Sets the size of the 51Degrees converter cache to <number> entries. This
1142 is an LRU cache which reminds previous device detections and their results.
1143 By default, this cache is disabled.
1144
1145 Please note that this option is only available when HAProxy has been
1146 compiled with USE_51DEGREES.
1147
1118ca-base <dir>1148ca-base <dir>
1119 Assigns a default directory to fetch SSL CA certificates and CRLs from when a1149 Assigns a default directory to fetch SSL CA certificates and CRLs from when a
1120 relative path is used with "ca-file", "ca-verify-file" or "crl-file"1150 relative path is used with "ca-file", "ca-verify-file" or "crl-file"
@@ -1267,6 +1297,13 @@ default-path { current | config | parent | origin <path> }
1267 paths. A robust approach could consist in prefixing all files names with1297 paths. A robust approach could consist in prefixing all files names with
1268 their respective site name, or in doing so at the directory level.1298 their respective site name, or in doing so at the directory level.
12691299
1300description <text>
1301 Add a text that describes the instance.
1302
1303 Please note that it is required to escape certain characters (# for example)
1304 and this text is inserted into a html page so you should avoid using
1305 "<" and ">" characters.
1306
1270deviceatlas-json-file <path>1307deviceatlas-json-file <path>
1271 Sets the path of the DeviceAtlas JSON data file to be loaded by the API.1308 Sets the path of the DeviceAtlas JSON data file to be loaded by the API.
1272 The path must be a valid JSON data file and accessible by HAProxy process.1309 The path must be a valid JSON data file and accessible by HAProxy process.
@@ -1275,15 +1312,15 @@ deviceatlas-log-level <value>
1275 Sets the level of information returned by the API. This directive is1312 Sets the level of information returned by the API. This directive is
1276 optional and set to 0 by default if not set.1313 optional and set to 0 by default if not set.
12771314
1278deviceatlas-separator <char>
1279 Sets the character separator for the API properties results. This directive
1280 is optional and set to | by default if not set.
1281
1282deviceatlas-properties-cookie <name>1315deviceatlas-properties-cookie <name>
1283 Sets the client cookie's name used for the detection if the DeviceAtlas1316 Sets the client cookie's name used for the detection if the DeviceAtlas
1284 Client-side component was used during the request. This directive is optional1317 Client-side component was used during the request. This directive is optional
1285 and set to DAPROPS by default if not set.1318 and set to DAPROPS by default if not set.
12861319
1320deviceatlas-separator <char>
1321 Sets the character separator for the API properties results. This directive
1322 is optional and set to | by default if not set.
1323
1287expose-experimental-directives1324expose-experimental-directives
1288 This statement must appear before using directives tagged as experimental or1325 This statement must appear before using directives tagged as experimental or
1289 the config file will be rejected.1326 the config file will be rejected.
@@ -1309,22 +1346,6 @@ group <group name>
1309 Similar to "gid" but uses the GID of group name <group name> from /etc/group.1346 Similar to "gid" but uses the GID of group name <group name> from /etc/group.
1310 See also "gid" and "user".1347 See also "gid" and "user".
13111348
1312hard-stop-after <time>
1313 Defines the maximum time allowed to perform a clean soft-stop.
1314
1315 Arguments :
1316 <time> is the maximum time (by default in milliseconds) for which the
1317 instance will remain alive when a soft-stop is received via the
1318 SIGUSR1 signal.
1319
1320 This may be used to ensure that the instance will quit even if connections
1321 remain opened during a soft-stop (for example with long timeouts for a proxy
1322 in tcp mode). It applies both in TCP and HTTP mode.
1323
1324 Example:
1325 global
1326 hard-stop-after 30s
1327
1328h1-case-adjust <from> <to>1349h1-case-adjust <from> <to>
1329 Defines the case adjustment to apply, when enabled, to the header name1350 Defines the case adjustment to apply, when enabled, to the header name
1330 <from>, to change it to <to> before sending it to HTTP/1 clients or1351 <from>, to change it to <to> before sending it to HTTP/1 clients or
@@ -1374,6 +1395,33 @@ h1-case-adjust-file <hdrs-file>
1374 See "h1-case-adjust", "option h1-case-adjust-bogus-client" and1395 See "h1-case-adjust", "option h1-case-adjust-bogus-client" and
1375 "option h1-case-adjust-bogus-server".1396 "option h1-case-adjust-bogus-server".
13761397
1398h2-workaround-bogus-websocket-clients
1399 This disables the announcement of the support for h2 websockets to clients.
1400 This can be use to overcome clients which have issues when implementing the
1401 relatively fresh RFC8441, such as Firefox 88. To allow clients to
1402 automatically downgrade to http/1.1 for the websocket tunnel, specify h2
1403 support on the bind line using "alpn" without an explicit "proto" keyword. If
1404 this statement was previously activated, this can be disabled by prefixing
1405 the keyword with "no'.
1406
1407hard-stop-after <time>
1408 Defines the maximum time allowed to perform a clean soft-stop.
1409
1410 Arguments :
1411 <time> is the maximum time (by default in milliseconds) for which the
1412 instance will remain alive when a soft-stop is received via the
1413 SIGUSR1 signal.
1414
1415 This may be used to ensure that the instance will quit even if connections
1416 remain opened during a soft-stop (for example with long timeouts for a proxy
1417 in tcp mode). It applies both in TCP and HTTP mode.
1418
1419 Example:
1420 global
1421 hard-stop-after 30s
1422
1423 See also: grace
1424
1377insecure-fork-wanted1425insecure-fork-wanted
1378 By default HAProxy tries hard to prevent any thread and process creation1426 By default HAProxy tries hard to prevent any thread and process creation
1379 after it starts. Doing so is particularly important when using Lua files of1427 after it starts. Doing so is particularly important when using Lua files of
@@ -1421,15 +1469,6 @@ issuers-chain-path <dir>
1421 "issuers-chain-path" directory. All other certificates with the same issuer1469 "issuers-chain-path" directory. All other certificates with the same issuer
1422 will share the chain in memory.1470 will share the chain in memory.
14231471
1424h2-workaround-bogus-websocket-clients
1425 This disables the announcement of the support for h2 websockets to clients.
1426 This can be use to overcome clients which have issues when implementing the
1427 relatively fresh RFC8441, such as Firefox 88. To allow clients to
1428 automatically downgrade to http/1.1 for the websocket tunnel, specify h2
1429 support on the bind line using "alpn" without an explicit "proto" keyword. If
1430 this statement was previously activated, this can be disabled by prefixing
1431 the keyword with "no'.
1432
1433localpeer <name>1472localpeer <name>
1434 Sets the local instance's peer name. It will be ignored if the "-L"1473 Sets the local instance's peer name. It will be ignored if the "-L"
1435 command line argument is specified or if used after "peers" section1474 command line argument is specified or if used after "peers" section
@@ -1762,6 +1801,26 @@ server-state-file <file>
1762 configuration. See also "server-state-base" and "show servers state",1801 configuration. See also "server-state-base" and "show servers state",
1763 "load-server-state-from-file" and "server-state-file-name"1802 "load-server-state-from-file" and "server-state-file-name"
17641803
1804set-dumpable
1805 This option is better left disabled by default and enabled only upon a
1806 developer's request. If it has been enabled, it may still be forcibly
1807 disabled by prefixing it with the "no" keyword. It has no impact on
1808 performance nor stability but will try hard to re-enable core dumps that were
1809 possibly disabled by file size limitations (ulimit -f), core size limitations
1810 (ulimit -c), or "dumpability" of a process after changing its UID/GID (such
1811 as /proc/sys/fs/suid_dumpable on Linux). Core dumps might still be limited by
1812 the current directory's permissions (check what directory the file is started
1813 from), the chroot directory's permission (it may be needed to temporarily
1814 disable the chroot directive or to move it to a dedicated writable location),
1815 or any other system-specific constraint. For example, some Linux flavours are
1816 notorious for replacing the default core file with a path to an executable
1817 not even installed on the system (check /proc/sys/kernel/core_pattern). Often,
1818 simply writing "core", "core.%p" or "/var/log/core/core.%p" addresses the
1819 issue. When trying to enable this option waiting for a rare issue to
1820 re-appear, it's often a good idea to first try to obtain such a dump by
1821 issuing, for example, "kill -11" to the "haproxy" process and verify that it
1822 leaves a core where expected when dying.
1823
1765set-var <var-name> <expr>1824set-var <var-name> <expr>
1766 Sets the process-wide variable '<var-name>' to the result of the evaluation1825 Sets the process-wide variable '<var-name>' to the result of the evaluation
1767 of the sample expression <expr>. The variable '<var-name>' may only be a1826 of the sample expression <expr>. The variable '<var-name>' may only be a
@@ -1785,26 +1844,6 @@ setenv <name> <value>
1785 the configuration file sees the new value. See also "presetenv", "resetenv",1844 the configuration file sees the new value. See also "presetenv", "resetenv",
1786 and "unsetenv".1845 and "unsetenv".
17871846
1788set-dumpable
1789 This option is better left disabled by default and enabled only upon a
1790 developer's request. If it has been enabled, it may still be forcibly
1791 disabled by prefixing it with the "no" keyword. It has no impact on
1792 performance nor stability but will try hard to re-enable core dumps that were
1793 possibly disabled by file size limitations (ulimit -f), core size limitations
1794 (ulimit -c), or "dumpability" of a process after changing its UID/GID (such
1795 as /proc/sys/fs/suid_dumpable on Linux). Core dumps might still be limited by
1796 the current directory's permissions (check what directory the file is started
1797 from), the chroot directory's permission (it may be needed to temporarily
1798 disable the chroot directive or to move it to a dedicated writable location),
1799 or any other system-specific constraint. For example, some Linux flavours are
1800 notorious for replacing the default core file with a path to an executable
1801 not even installed on the system (check /proc/sys/kernel/core_pattern). Often,
1802 simply writing "core", "core.%p" or "/var/log/core/core.%p" addresses the
1803 issue. When trying to enable this option waiting for a rare issue to
1804 re-appear, it's often a good idea to first try to obtain such a dump by
1805 issuing, for example, "kill -11" to the "haproxy" process and verify that it
1806 leaves a core where expected when dying.
1807
1808ssl-default-bind-ciphers <ciphers>1847ssl-default-bind-ciphers <ciphers>
1809 This setting is only available when support for OpenSSL was built in. It sets1848 This setting is only available when support for OpenSSL was built in. It sets
1810 the default string describing the list of cipher algorithms ("cipher suite")1849 the default string describing the list of cipher algorithms ("cipher suite")
@@ -1995,6 +2034,10 @@ ssl-skip-self-issued-ca
1995 certificates. It's useless for BoringSSL, .issuer is ignored because ocsp2034 certificates. It's useless for BoringSSL, .issuer is ignored because ocsp
1996 bits does not need it. Requires at least OpenSSL 1.0.2.2035 bits does not need it. Requires at least OpenSSL 1.0.2.
19972036
2037stats maxconn <connections>
2038 By default, the stats socket is limited to 10 concurrent connections. It is
2039 possible to change this value with "stats maxconn".
2040
1998stats socket [<address:port>|<path>] [param*]2041stats socket [<address:port>|<path>] [param*]
1999 Binds a UNIX socket to <path> or a TCPv4/v6 address to <address:port>.2042 Binds a UNIX socket to <path> or a TCPv4/v6 address to <address:port>.
2000 Connections to this socket will return various statistics outputs and even2043 Connections to this socket will return various statistics outputs and even
@@ -2011,9 +2054,12 @@ stats timeout <timeout, in milliseconds>
2011 to change this value with "stats timeout". The value must be passed in2054 to change this value with "stats timeout". The value must be passed in
2012 milliseconds, or be suffixed by a time unit among { us, ms, s, m, h, d }.2055 milliseconds, or be suffixed by a time unit among { us, ms, s, m, h, d }.
20132056
2014stats maxconn <connections>2057strict-limits
2015 By default, the stats socket is limited to 10 concurrent connections. It is2058 Makes process fail at startup when a setrlimit fails. HAProxy tries to set the
2016 possible to change this value with "stats maxconn".2059 best setrlimit according to what has been calculated. If it fails, it will
2060 emit a warning. This option is here to guarantee an explicit failure of
2061 HAProxy when those limits fail. It is enabled by default. It may still be
2062 forcibly disabled by prefixing it with the "no" keyword.
20172063
2018uid <number>2064uid <number>
2019 Changes the process's user ID to <number>. It is recommended that the user ID2065 Changes the process's user ID to <number>. It is recommended that the user ID
@@ -2061,42 +2107,14 @@ node <name>
2061 nodes, it becomes easy to immediately spot what server is handling the2107 nodes, it becomes easy to immediately spot what server is handling the
2062 traffic.2108 traffic.
20632109
2064description <text>2110wurfl-cache-size <size>
2065 Add a text that describes the instance.2111 Sets the WURFL Useragent cache size. For faster lookups, already processed user
20662112 agents are kept in a LRU cache :
2067 Please note that it is required to escape certain characters (# for example)2113 - "0" : no cache is used.
2068 and this text is inserted into a html page so you should avoid using2114 - <size> : size of lru cache in elements.
2069 "<" and ">" characters.
2070
207151degrees-data-file <file path>
2072 The path of the 51Degrees data file to provide device detection services. The
2073 file should be unzipped and accessible by HAProxy with relevant permissions.
2074
2075 Please note that this option is only available when HAProxy has been
2076 compiled with USE_51DEGREES.
2077
207851degrees-property-name-list [<string> ...]
2079 A list of 51Degrees property names to be load from the dataset. A full list
2080 of names is available on the 51Degrees website:
2081 https://51degrees.com/resources/property-dictionary
2082
2083 Please note that this option is only available when HAProxy has been
2084 compiled with USE_51DEGREES.
2085
208651degrees-property-separator <char>
2087 A char that will be appended to every property value in a response header
2088 containing 51Degrees results. If not set that will be set as ','.
2089
2090 Please note that this option is only available when HAProxy has been
2091 compiled with USE_51DEGREES.
2092
209351degrees-cache-size <number>
2094 Sets the size of the 51Degrees converter cache to <number> entries. This
2095 is an LRU cache which reminds previous device detections and their results.
2096 By default, this cache is disabled.
20972115
2098 Please note that this option is only available when HAProxy has been2116 Please note that this option is only available when HAProxy has been compiled
2099 compiled with USE_51DEGREES.2117 with USE_WURFL=1.
21002118
2101wurfl-data-file <file path>2119wurfl-data-file <file path>
2102 The path of the WURFL data file to provide device detection services. The2120 The path of the WURFL data file to provide device detection services. The
@@ -2152,22 +2170,6 @@ wurfl-patch-file [<file path>]
2152 Please note that this option is only available when HAProxy has been compiled2170 Please note that this option is only available when HAProxy has been compiled
2153 with USE_WURFL=1.2171 with USE_WURFL=1.
21542172
2155wurfl-cache-size <size>
2156 Sets the WURFL Useragent cache size. For faster lookups, already processed user
2157 agents are kept in a LRU cache :
2158 - "0" : no cache is used.
2159 - <size> : size of lru cache in elements.
2160
2161 Please note that this option is only available when HAProxy has been compiled
2162 with USE_WURFL=1.
2163
2164strict-limits
2165 Makes process fail at startup when a setrlimit fails. HAProxy tries to set the
2166 best setrlimit according to what has been calculated. If it fails, it will
2167 emit a warning. This option is here to guarantee an explicit failure of
2168 HAProxy when those limits fail. It is enabled by default. It may still be
2169 forcibly disabled by prefixing it with the "no" keyword.
2170
21713.2. Performance tuning21733.2. Performance tuning
2172-----------------------2174-----------------------
21732175
@@ -2204,6 +2206,24 @@ max-spread-checks <delay in milliseconds>
2204 even if the servers' check intervals are larger. When servers run with2206 even if the servers' check intervals are larger. When servers run with
2205 shorter intervals, their intervals will be respected though.2207 shorter intervals, their intervals will be respected though.
22062208
2209maxcompcpuusage <number>
2210 Sets the maximum CPU usage HAProxy can reach before stopping the compression
2211 for new requests or decreasing the compression level of current requests.
2212 It works like 'maxcomprate' but measures CPU usage instead of incoming data
2213 bandwidth. The value is expressed in percent of the CPU used by HAProxy. A
2214 value of 100 disable the limit. The default value is 100. Setting a lower
2215 value will prevent the compression work from slowing the whole process down
2216 and from introducing high latencies.
2217
2218maxcomprate <number>
2219 Sets the maximum per-process input compression rate to <number> kilobytes
2220 per second. For each session, if the maximum is reached, the compression
2221 level will be decreased during the session. If the maximum is reached at the
2222 beginning of a session, the session will not compress at all. If the maximum
2223 is not reached, the compression level will be increased up to
2224 tune.comp.maxlevel. A value of zero means there is no limit, this is the
2225 default value.
2226
2207maxconn <number>2227maxconn <number>
2208 Sets the maximum per-process number of concurrent connections to <number>. It2228 Sets the maximum per-process number of concurrent connections to <number>. It
2209 is equivalent to the command-line argument "-n". Proxies will stop accepting2229 is equivalent to the command-line argument "-n". Proxies will stop accepting
@@ -2229,25 +2249,6 @@ maxconnrate <number>
2229 value close to its expected share. Also, lowering tune.maxaccept can improve2249 value close to its expected share. Also, lowering tune.maxaccept can improve
2230 fairness.2250 fairness.
22312251
2232maxcomprate <number>
2233 Sets the maximum per-process input compression rate to <number> kilobytes
2234 per second. For each session, if the maximum is reached, the compression
2235 level will be decreased during the session. If the maximum is reached at the
2236 beginning of a session, the session will not compress at all. If the maximum
2237 is not reached, the compression level will be increased up to
2238 tune.comp.maxlevel. A value of zero means there is no limit, this is the
2239 default value.
2240
2241maxcompcpuusage <number>
2242 Sets the maximum CPU usage HAProxy can reach before stopping the compression
2243 for new requests or decreasing the compression level of current requests.
2244 It works like 'maxcomprate' but measures CPU usage instead of incoming data
2245 bandwidth. The value is expressed in percent of the CPU used by HAProxy. In
2246 case of multiple processes (nbproc > 1), each process manages its individual
2247 usage. A value of 100 disable the limit. The default value is 100. Setting
2248 a lower value will prevent the compression work from slowing the whole
2249 process down and from introducing high latencies.
2250
2251maxpipes <number>2252maxpipes <number>
2252 Sets the maximum per-process number of pipes to <number>. Currently, pipes2253 Sets the maximum per-process number of pipes to <number>. Currently, pipes
2253 are only used by kernel-based tcp splicing. Since a pipe contains two file2254 are only used by kernel-based tcp splicing. Since a pipe contains two file
@@ -2323,17 +2324,21 @@ noepoll
2323 equivalent to the command-line argument "-de". The next polling system2324 equivalent to the command-line argument "-de". The next polling system
2324 used will generally be "poll". See also "nopoll".2325 used will generally be "poll". See also "nopoll".
23252326
2326nokqueue
2327 Disables the use of the "kqueue" event polling system on BSD. It is
2328 equivalent to the command-line argument "-dk". The next polling system
2329 used will generally be "poll". See also "nopoll".
2330
2331noevports2327noevports
2332 Disables the use of the event ports event polling system on SunOS systems2328 Disables the use of the event ports event polling system on SunOS systems
2333 derived from Solaris 10 and later. It is equivalent to the command-line2329 derived from Solaris 10 and later. It is equivalent to the command-line
2334 argument "-dv". The next polling system used will generally be "poll". See2330 argument "-dv". The next polling system used will generally be "poll". See
2335 also "nopoll".2331 also "nopoll".
23362332
2333nogetaddrinfo
2334 Disables the use of getaddrinfo(3) for name resolving. It is equivalent to
2335 the command line argument "-dG". Deprecated gethostbyname(3) will be used.
2336
2337nokqueue
2338 Disables the use of the "kqueue" event polling system on BSD. It is
2339 equivalent to the command-line argument "-dk". The next polling system
2340 used will generally be "poll". See also "nopoll".
2341
2337nopoll2342nopoll
2338 Disables the use of the "poll" event polling system. It is equivalent to the2343 Disables the use of the "poll" event polling system. It is equivalent to the
2339 command-line argument "-dp". The next polling system used will be "select".2344 command-line argument "-dp". The next polling system used will be "select".
@@ -2341,6 +2346,10 @@ nopoll
2341 platforms supported by HAProxy. See also "nokqueue", "noepoll" and2346 platforms supported by HAProxy. See also "nokqueue", "noepoll" and
2342 "noevports".2347 "noevports".
23432348
2349noreuseport
2350 Disables the use of SO_REUSEPORT - see socket(7). It is equivalent to the
2351 command line argument "-dR".
2352
2344nosplice2353nosplice
2345 Disables the use of kernel tcp splicing between sockets on Linux. It is2354 Disables the use of kernel tcp splicing between sockets on Linux. It is
2346 equivalent to the command line argument "-dS". Data will then be copied2355 equivalent to the command line argument "-dS". Data will then be copied
@@ -2351,14 +2360,6 @@ nosplice
2351 case of doubt. See also "option splice-auto", "option splice-request" and2360 case of doubt. See also "option splice-auto", "option splice-request" and
2352 "option splice-response".2361 "option splice-response".
23532362
2354nogetaddrinfo
2355 Disables the use of getaddrinfo(3) for name resolving. It is equivalent to
2356 the command line argument "-dG". Deprecated gethostbyname(3) will be used.
2357
2358noreuseport
2359 Disables the use of SO_REUSEPORT - see socket(7). It is equivalent to the
2360 command line argument "-dR".
2361
2362profiling.memory { on | off }2363profiling.memory { on | off }
2363 Enables ('on') or disables ('off') per-function memory profiling. This will2364 Enables ('on') or disables ('off') per-function memory profiling. This will
2364 keep usage statistics of malloc/calloc/realloc/free calls anywhere in the2365 keep usage statistics of malloc/calloc/realloc/free calls anywhere in the
@@ -2604,18 +2605,18 @@ tune.lua.session-timeout <timeout>
2604 counts only the pure Lua runtime. If the Lua does a sleep, the sleep is2605 counts only the pure Lua runtime. If the Lua does a sleep, the sleep is
2605 not taken in account. The default timeout is 4s.2606 not taken in account. The default timeout is 4s.
26062607
2607tune.lua.task-timeout <timeout>
2608 Purpose is the same as "tune.lua.session-timeout", but this timeout is
2609 dedicated to the tasks. By default, this timeout isn't set because a task may
2610 remain alive during of the lifetime of HAProxy. For example, a task used to
2611 check servers.
2612
2613tune.lua.service-timeout <timeout>2608tune.lua.service-timeout <timeout>
2614 This is the execution timeout for the Lua services. This is useful for2609 This is the execution timeout for the Lua services. This is useful for
2615 preventing infinite loops or spending too much time in Lua. This timeout2610 preventing infinite loops or spending too much time in Lua. This timeout
2616 counts only the pure Lua runtime. If the Lua does a sleep, the sleep is2611 counts only the pure Lua runtime. If the Lua does a sleep, the sleep is
2617 not taken in account. The default timeout is 4s.2612 not taken in account. The default timeout is 4s.
26182613
2614tune.lua.task-timeout <timeout>
2615 Purpose is the same as "tune.lua.session-timeout", but this timeout is
2616 dedicated to the tasks. By default, this timeout isn't set because a task may
2617 remain alive during of the lifetime of HAProxy. For example, a task used to
2618 check servers.
2619
2619tune.maxaccept <number>2620tune.maxaccept <number>
2620 Sets the maximum number of consecutive connections a process may accept in a2621 Sets the maximum number of consecutive connections a process may accept in a
2621 row before switching to other work. In single process mode, higher numbers2622 row before switching to other work. In single process mode, higher numbers
@@ -2756,6 +2757,26 @@ tune.ssl.cachesize <number>
2756 pre-allocated upon startup and are shared between all processes if "nbproc"2757 pre-allocated upon startup and are shared between all processes if "nbproc"
2757 is greater than 1. Setting this value to 0 disables the SSL session cache.2758 is greater than 1. Setting this value to 0 disables the SSL session cache.
27582759
2760tune.ssl.capture-cipherlist-size <number>
2761 Sets the maximum size of the buffer used for capturing client hello cipher
2762 list, extensions list, elliptic curves list and elliptic curve point
2763 formats. If the value is 0 (default value) the capture is disabled,
2764 otherwise a buffer is allocated for each SSL/TLS connection.
2765
2766tune.ssl.default-dh-param <number>
2767 Sets the maximum size of the Diffie-Hellman parameters used for generating
2768 the ephemeral/temporary Diffie-Hellman key in case of DHE key exchange. The
2769 final size will try to match the size of the server's RSA (or DSA) key (e.g,
2770 a 2048 bits temporary DH key for a 2048 bits RSA key), but will not exceed
2771 this maximum value. Only 1024 or higher values are allowed. Higher values
2772 will increase the CPU load, and values greater than 1024 bits are not
2773 supported by Java 7 and earlier clients. This value is not used if static
2774 Diffie-Hellman parameters are supplied either directly in the certificate
2775 file or by using the ssl-dh-param-file parameter.
2776 If there is neither a default-dh-param nor a ssl-dh-param-file defined, and
2777 if the server's PEM file of a given frontend does not specify its own DH
2778 parameters, then DHE ciphers will be unavailable for this frontend.
2779
2759tune.ssl.force-private-cache2780tune.ssl.force-private-cache
2760 This option disables SSL session cache sharing between all processes. It2781 This option disables SSL session cache sharing between all processes. It
2761 should normally not be used since it will force many renegotiations due to2782 should normally not be used since it will force many renegotiations due to
@@ -2824,28 +2845,12 @@ tune.ssl.maxrecord <number>
2824 best value. HAProxy will automatically switch to this setting after an idle2845 best value. HAProxy will automatically switch to this setting after an idle
2825 stream has been detected (see tune.idletimer above).2846 stream has been detected (see tune.idletimer above).
28262847
2827tune.ssl.default-dh-param <number>
2828 Sets the maximum size of the Diffie-Hellman parameters used for generating
2829 the ephemeral/temporary Diffie-Hellman key in case of DHE key exchange. The
2830 final size will try to match the size of the server's RSA (or DSA) key (e.g,
2831 a 2048 bits temporary DH key for a 2048 bits RSA key), but will not exceed
2832 this maximum value. Default value if 2048. Only 1024 or higher values are
2833 allowed. Higher values will increase the CPU load, and values greater than
2834 1024 bits are not supported by Java 7 and earlier clients. This value is not
2835 used if static Diffie-Hellman parameters are supplied either directly
2836 in the certificate file or by using the ssl-dh-param-file parameter.
2837
2838tune.ssl.ssl-ctx-cache-size <number>2848tune.ssl.ssl-ctx-cache-size <number>
2839 Sets the size of the cache used to store generated certificates to <number>2849 Sets the size of the cache used to store generated certificates to <number>
2840 entries. This is a LRU cache. Because generating a SSL certificate2850 entries. This is a LRU cache. Because generating a SSL certificate
2841 dynamically is expensive, they are cached. The default cache size is set to2851 dynamically is expensive, they are cached. The default cache size is set to
2842 1000 entries.2852 1000 entries.
28432853
2844tune.ssl.capture-cipherlist-size <number>
2845 Sets the maximum size of the buffer used for capturing client-hello cipher
2846 list. If the value is 0 (default value) the capture is disabled, otherwise
2847 a buffer is allocated for each SSL/TLS connection.
2848
2849tune.vars.global-max-size <size>2854tune.vars.global-max-size <size>
2850tune.vars.proc-max-size <size>2855tune.vars.proc-max-size <size>
2851tune.vars.reqres-max-size <size>2856tune.vars.reqres-max-size <size>
@@ -3619,7 +3624,7 @@ http-error X X X X
3619http-request - X X X3624http-request - X X X
3620http-response - X X X3625http-response - X X X
3621http-reuse X - X X3626http-reuse X - X X
3622http-send-name-header - - X X3627http-send-name-header X - X X
3623id - X X X3628id - X X X
3624ignore-persist - - X X3629ignore-persist - - X X
3625load-server-state-from-file X - X X3630load-server-state-from-file X - X X
@@ -3677,7 +3682,7 @@ option socket-stats (*) X X X -
3677option splice-auto (*) X X X X3682option splice-auto (*) X X X X
3678option splice-request (*) X X X X3683option splice-request (*) X X X X
3679option splice-response (*) X X X X3684option splice-response (*) X X X X
3680option spop-check - - - X3685option spop-check X - X X
3681option srvtcpka (*) X - X X3686option srvtcpka (*) X - X X
3682option ssl-hello-chk X - X X3687option ssl-hello-chk X - X X
3683-- keyword -------------------------- defaults - frontend - listen -- backend -3688-- keyword -------------------------- defaults - frontend - listen -- backend -
@@ -6162,7 +6167,8 @@ http-request do-resolve(<var>,<resolvers>,[ipv4,ipv6]) <expr> :
6162 based on information found in the request (IE a Host header).6167 based on information found in the request (IE a Host header).
6163 If this action is used to find the server's IP address (using the6168 If this action is used to find the server's IP address (using the
6164 "set-dst" action), then the server IP address in the backend must be set6169 "set-dst" action), then the server IP address in the backend must be set
6165 to 0.0.0.0.6170 to 0.0.0.0. The do-resolve action takes an host-only parameter, any port must
6171 be removed from the string.
61666172
6167 Example:6173 Example:
6168 resolvers mydns6174 resolvers mydns
@@ -6177,7 +6183,7 @@ http-request do-resolve(<var>,<resolvers>,[ipv4,ipv6]) <expr> :
61776183
6178 frontend fe6184 frontend fe
6179 bind 10.42.0.1:806185 bind 10.42.0.1:80
6180 http-request do-resolve(txn.myip,mydns,ipv4) hdr(Host),lower6186 http-request do-resolve(txn.myip,mydns,ipv4) hdr(Host),lower,regsub(:[0-9]*$,)
6181 http-request capture var(txn.myip) len 406187 http-request capture var(txn.myip) len 40
61826188
6183 # return 503 when the variable is not set,6189 # return 503 when the variable is not set,
@@ -6814,9 +6820,11 @@ http-request set-uri <fmt> [ { if | unless } <condition> ]
68146820
6815 This rewrites the request URI with the result of the evaluation of format6821 This rewrites the request URI with the result of the evaluation of format
6816 string <fmt>. The scheme, authority, path and query string are all replaced6822 string <fmt>. The scheme, authority, path and query string are all replaced
6817 at once. This can be used to rewrite hosts in front of proxies, or to6823 at once. This can be used to rewrite hosts in front of proxies, or to perform
6818 perform complex modifications to the URI such as moving parts between the6824 complex modifications to the URI such as moving parts between the path and
6819 path and the query string.6825 the query string. If an absolute URI is set, it will be sent as is to
6826 HTTP/1.1 servers. If it is not the desired behavior, the host, the path
6827 and/or the query string should be set separately.
6820 See also "http-request set-path" and "http-request set-query".6828 See also "http-request set-path" and "http-request set-query".
68216829
6822http-request set-var(<var-name>) <expr> [ { if | unless } <condition> ]6830http-request set-var(<var-name>) <expr> [ { if | unless } <condition> ]
@@ -7541,7 +7549,26 @@ http-reuse { never | safe | aggressive | always }
7541 because almost no new connection will be established while idle connections7549 because almost no new connection will be established while idle connections
7542 remain available. This is particularly true with the "always" strategy.7550 remain available. This is particularly true with the "always" strategy.
75437551
7544 See also : "option http-keep-alive", "server maxconn"7552 The rules to decide to keep an idle connection opened or to close it after
7553 processing are also governed by the "tune.pool-low-fd-ratio" (default: 20%)
7554 and "tune.pool-high-fd-ratio" (default: 25%). These correspond to the
7555 percentage of total file descriptors spent in idle connections above which
7556 haproxy will respectively refrain from keeping a connection opened after a
7557 response, and actively kill idle connections. Some setups using a very high
7558 ratio of idle connections, either because of too low a global "maxconn", or
7559 due to a lot of HTTP/2 or HTTP/3 traffic on the frontend (few connections)
7560 but HTTP/1 connections on the backend, may observe a lower reuse rate because
7561 too few connections are kept open. It may be desirable in this case to adjust
7562 such thresholds or simply to increase the global "maxconn" value.
7563
7564 Similarly, when thread groups are explicitly enabled, it is important to
7565 understand that idle connections are only usable between threads from a same
7566 group. As such it may happen that unfair load between groups leads to more
7567 idle connections being needed, causing a lower reuse rate. The same solution
7568 may then be applied (increase global "maxconn" or increase pool ratios).
7569
7570 See also : "option http-keep-alive", "server maxconn", "thread-groups",
7571 "tune.pool-high-fd-ratio", "tune.pool-low-fd-ratio"
75457572
75467573
7547http-send-name-header [<header>]7574http-send-name-header [<header>]
@@ -8073,7 +8100,9 @@ monitor-uri <uri>
8073 Monitor requests are processed very early, just after the request is parsed8100 Monitor requests are processed very early, just after the request is parsed
8074 and even before any "http-request". The only rulesets applied before are the8101 and even before any "http-request". The only rulesets applied before are the
8075 tcp-request ones. They cannot be logged either, and it is the intended8102 tcp-request ones. They cannot be logged either, and it is the intended
8076 purpose. They are only used to report HAProxy's health to an upper component,8103 purpose. Only one URI may be configured for monitoring; when multiple
8104 "monitor-uri" statements are present, the last one will define the URI to
8105 be used. They are only used to report HAProxy's health to an upper component,
8077 nothing more. However, it is possible to add any number of conditions using8106 nothing more. However, it is possible to add any number of conditions using
8078 "monitor fail" and ACLs so that the result can be adjusted to whatever check8107 "monitor fail" and ACLs so that the result can be adjusted to whatever check
8079 can be imagined (most often the number of available servers in a backend).8108 can be imagined (most often the number of available servers in a backend).
@@ -9350,7 +9379,7 @@ no option persist
9350 See also : "option redispatch", "retries", "force-persist"9379 See also : "option redispatch", "retries", "force-persist"
93519380
93529381
9353option pgsql-check [ user <username> ]9382option pgsql-check user <username>
9354 Use PostgreSQL health checks for server testing9383 Use PostgreSQL health checks for server testing
9355 May be used in sections : defaults | frontend | listen | backend9384 May be used in sections : defaults | frontend | listen | backend
9356 yes | no | yes | yes9385 yes | no | yes | yes
@@ -9610,7 +9639,7 @@ no option splice-response
9610option spop-check9639option spop-check
9611 Use SPOP health checks for server testing9640 Use SPOP health checks for server testing
9612 May be used in sections : defaults | frontend | listen | backend9641 May be used in sections : defaults | frontend | listen | backend
9613 no | no | no | yes9642 yes | no | yes | yes
9614 Arguments : none9643 Arguments : none
96159644
9616 It is possible to test that the server correctly talks SPOP protocol instead9645 It is possible to test that the server correctly talks SPOP protocol instead
@@ -10175,24 +10204,26 @@ redirect scheme <sch> [code <code>] <option> [{if | unless} <condition>]
1017510204
1017610205
10177retries <value>10206retries <value>
10178 Set the number of retries to perform on a server after a connection failure10207 Set the number of retries to perform on a server after a failure
10179 May be used in sections: defaults | frontend | listen | backend10208 May be used in sections: defaults | frontend | listen | backend
10180 yes | no | yes | yes10209 yes | no | yes | yes
10181 Arguments :10210 Arguments :
10182 <value> is the number of times a connection attempt should be retried on10211 <value> is the number of times a request or connection attempt should be
10183 a server when a connection either is refused or times out. The10212 retried on a server after a failure.
10184 default value is 3.
1018510213
10186 It is important to understand that this value applies to the number of10214 By default, retries apply only to new connection attempts. However, when
10187 connection attempts, not full requests. When a connection has effectively10215 the "retry-on" directive is used, other conditions might trigger a retry
10188 been established to a server, there will be no more retry.10216 (e.g. empty response, undesired status code), and each of them will count
10217 one attempt, and when the total number attempts reaches the value here, an
10218 error will be returned.
1018910219
10190 In order to avoid immediate reconnections to a server which is restarting,10220 In order to avoid immediate reconnections to a server which is restarting,
10191 a turn-around timer of min("timeout connect", one second) is applied before10221 a turn-around timer of min("timeout connect", one second) is applied before
10192 a retry occurs.10222 a retry occurs on the same server.
1019310223
10194 When "option redispatch" is set, the last retry may be performed on another10224 When "option redispatch" is set, some retries may be performed on another
10195 server even if a cookie references a different server.10225 server even if a cookie references a different server. By default this will
10226 only be the last retry unless an argument is passed to "option redispatch".
1019610227
10197 See also : "option redispatch"10228 See also : "option redispatch"
1019810229
@@ -12423,7 +12454,7 @@ tcp-request content <action> [{if | unless} <condition>]
12423 evaluated.12454 evaluated.
1242412455
12425 Example:12456 Example:
12426 tcp-request content use-service lua.deny { src -f /etc/haproxy/blacklist.lst }12457 tcp-request content use-service lua.deny if { src -f /etc/haproxy/blacklist.lst }
1242712458
12428 Example:12459 Example:
1242912460
@@ -14986,8 +15017,10 @@ sni <expression>
14986 The "sni" parameter evaluates the sample fetch expression, converts it to a15017 The "sni" parameter evaluates the sample fetch expression, converts it to a
14987 string and uses the result as the host name sent in the SNI TLS extension to15018 string and uses the result as the host name sent in the SNI TLS extension to
14988 the server. A typical use case is to send the SNI received from the client in15019 the server. A typical use case is to send the SNI received from the client in
14989 a bridged HTTPS scenario, using the "ssl_fc_sni" sample fetch for the15020 a bridged TCP/SSL scenario, using the "ssl_fc_sni" sample fetch for the
14990 expression, though alternatives such as req.hdr(host) can also make sense. If15021 expression. THIS MUST NOT BE USED FOR HTTPS, where req.hdr(host) should be
15022 used instead, since SNI in HTTPS must always match the Host field and clients
15023 are allowed to use different host names over the same connection). If
14991 "verify required" is set (which is the recommended setting), the resulting15024 "verify required" is set (which is the recommended setting), the resulting
14992 name will also be matched against the server certificate's names. See the15025 name will also be matched against the server certificate's names. See the
14993 "verify" directive for more details. If you want to set a SNI for health15026 "verify" directive for more details. If you want to set a SNI for health
@@ -15679,7 +15712,11 @@ possible to convert the sample to lowercase before matching, like this :
15679All ACL-specific criteria imply a default matching method. Most often, these15712All ACL-specific criteria imply a default matching method. Most often, these
15680criteria are composed by concatenating the name of the original sample fetch15713criteria are composed by concatenating the name of the original sample fetch
15681method and the matching method. For example, "hdr_beg" applies the "beg" match15714method and the matching method. For example, "hdr_beg" applies the "beg" match
15682to samples retrieved using the "hdr" fetch method. Since all ACL-specific15715to samples retrieved using the "hdr" fetch method. This matching method is only
15716usable when the keyword is used alone, without any converter. In case any such
15717converter were to be applied after such an ACL keyword, the default matching
15718method from the ACL keyword is simply ignored since what will matter for the
15719matching is the output type of the last converter. Since all ACL-specific
15683criteria rely on a sample fetch method, it is always possible instead to use15720criteria rely on a sample fetch method, it is always possible instead to use
15684the original sample fetch method and the explicit matching method using "-m".15721the original sample fetch method and the explicit matching method using "-m".
1568515722
@@ -15805,13 +15842,24 @@ different forms :
15805 - suffix match (-m end) : the patterns are compared with the end of the15842 - suffix match (-m end) : the patterns are compared with the end of the
15806 extracted string, and the ACL matches if any of them matches.15843 extracted string, and the ACL matches if any of them matches.
1580715844
15808 - subdir match (-m dir) : the patterns are looked up inside the extracted15845 - subdir match (-m dir) : the patterns are looked up anywhere inside the
15809 string, delimited with slashes ("/"), and the ACL matches if any of them15846 extracted string, delimited with slashes ("/"), the beginning or the end
15810 matches.15847 of the string. The ACL matches if any of them matches. As such, the string
1581115848 "/images/png/logo/32x32.png", would match "/images", "/images/png",
15812 - domain match (-m dom) : the patterns are looked up inside the extracted15849 "images/png", "/png/logo", "logo/32x32.png" or "32x32.png" but not "png"
15813 string, delimited with dots ("."), and the ACL matches if any of them15850 nor "32x32".
15814 matches.15851
15852 - domain match (-m dom) : the patterns are looked up anywhere inside the
15853 extracted string, delimited with dots ("."), colons (":"), slashes ("/"),
15854 question marks ("?"), the beginning or the end of the string. This is made
15855 to be used with URLs. Leading and trailing delimiters in the pattern are
15856 ignored. The ACL matches if any of them matches. As such, in the example
15857 string "http://www1.dc-eu.example.com:80/blah", the patterns "http",
15858 "www1", ".www1", "dc-eu", "example", "com", "80", "dc-eu.example",
15859 "blah", ":www1:", "dc-eu.example:80" would match, but not "eu" nor "dc".
15860 Using it to match domain suffixes for filtering or routing is generally
15861 not a good idea, as the routing could easily be fooled by prepending the
15862 matching prefix in front of another domain for example.
1581515863
15816String matching applies to verbatim strings as they are passed, with the15864String matching applies to verbatim strings as they are passed, with the
15817exception of the backslash ("\") which makes it possible to escape some15865exception of the backslash ("\") which makes it possible to escape some
@@ -18860,6 +18908,16 @@ ssl_fc_sni : string
18860 requires that the SSL library is built with support for TLS extensions18908 requires that the SSL library is built with support for TLS extensions
18861 enabled (check haproxy -vv).18909 enabled (check haproxy -vv).
1886218910
18911 CAUTION! Except under very specific conditions, it is normally not correct to
18912 use this field as a substitute for the HTTP "Host" header field. For example,
18913 when forwarding an HTTPS connection to a server, the SNI field must be set
18914 from the HTTP Host header field using "req.hdr(host)" and not from the front
18915 SNI value. The reason is that SNI is solely used to select the certificate
18916 the server side will present, and that clients are then allowed to send
18917 requests with different Host values as long as they match the names in the
18918 certificate. As such, "ssl_fc_sni" should normally not be used as an argument
18919 to the "sni" server keyword, unless the backend works in TCP mode.
18920
18863 ACL derivatives :18921 ACL derivatives :
18864 ssl_fc_sni_end : suffix match18922 ssl_fc_sni_end : suffix match
18865 ssl_fc_sni_reg : regex match18923 ssl_fc_sni_reg : regex match
@@ -22093,8 +22151,8 @@ Optionally, a prefix could be used to force the address family and/or the
22093socket type and the transport method.22151socket type and the transport method.
2209422152
2209522153
2209611.1 Address family prefixes2215411.1. Address family prefixes
22097----------------------------22155-----------------------------
2209822156
22099'abns@<name>' following <name> is an abstract namespace (Linux only).22157'abns@<name>' following <name> is an abstract namespace (Linux only).
2210022158
@@ -22129,8 +22187,8 @@ socket type and the transport method.
22129 start by slash '/'.22187 start by slash '/'.
2213022188
2213122189
2213211.2 Socket type prefixes2219011.2. Socket type prefixes
22133-------------------------22191--------------------------
2213422192
22135Previous "Address family prefixes" can also be prefixed to force the socket22193Previous "Address family prefixes" can also be prefixed to force the socket
22136type and the transport method. The default depends of the statement using22194type and the transport method. The default depends of the statement using
@@ -22139,7 +22197,7 @@ This is the case for "log" statement where the default is syslog over UDP
22139but we could force to use syslog over TCP.22197but we could force to use syslog over TCP.
2214022198
22141Those prefixes were designed for internal purpose and users should22199Those prefixes were designed for internal purpose and users should
22142instead use aliases of the next section "11.5.3 Protocol prefixes".22200instead use aliases of the next section "11.3 Protocol prefixes".
2214322201
22144If users need one those prefixes to perform what they expect because22202If users need one those prefixes to perform what they expect because
22145they can not configure the same using the protocol prefixes, they should22203they can not configure the same using the protocol prefixes, they should
@@ -22152,8 +22210,8 @@ report this to the maintainers.
22152 to "datagram".22210 to "datagram".
2215322211
2215422212
2215511.3 Protocol prefixes2221311.3. Protocol prefixes
22156----------------------22214-----------------------
2215722215
22158'tcp@<address>[:port1[-port2]]' following <address> is considered as an IPv422216'tcp@<address>[:port1[-port2]]' following <address> is considered as an IPv4
22159 or IPv6 address depending of the syntax but22217 or IPv6 address depending of the syntax but
@@ -22190,14 +22248,14 @@ report this to the maintainers.
22190 method is forced to "datagram". Depending on22248 method is forced to "datagram". Depending on
22191 the statement using this address, a port or22249 the statement using this address, a port or
22192 port range can or must be specified.22250 port range can or must be specified.
22193 It is considered as an alias of 'stream+ipv4@'.22251 It is considered as an alias of 'dgram+ipv4@'.
2219422252
22195'udp6@<address>[:port1[-port2]]' following <address> is always considered as22253'udp6@<address>[:port1[-port2]]' following <address> is always considered as
22196 an IPv6 address but socket type and transport22254 an IPv6 address but socket type and transport
22197 method is forced to "datagram". Depending on22255 method is forced to "datagram". Depending on
22198 the statement using this address, a port or22256 the statement using this address, a port or
22199 port range can or must be specified.22257 port range can or must be specified.
22200 It is considered as an alias of 'stream+ipv4@'.22258 It is considered as an alias of 'dgram+ipv4@'.
2220122259
22202'uxdg@<path>' following string is considered as a unix socket <path> but22260'uxdg@<path>' following string is considered as a unix socket <path> but
22203 transport method is forced to "datagram". It is considered as22261 transport method is forced to "datagram". It is considered as
diff --git a/doc/intro.txt b/doc/intro.txt
index 325ba76..d6e8648 100644
--- a/doc/intro.txt
+++ b/doc/intro.txt
@@ -41,6 +41,7 @@ Summary
413.3.5. Load balancing413.3.5. Load balancing
423.3.6. Stickiness423.3.6. Stickiness
433.3.7. Logging433.3.7. Logging
443.3.8. Statistics
443.4. Standard features453.4. Standard features
453.4.1. Sampling and converting information463.4.1. Sampling and converting information
463.4.2. Maps473.4.2. Maps
@@ -50,7 +51,6 @@ Summary
503.4.6. Formatted strings513.4.6. Formatted strings
513.4.7. HTTP rewriting and redirection523.4.7. HTTP rewriting and redirection
523.4.8. Server protection533.4.8. Server protection
533.4.9. Statistics
543.5. Advanced features543.5. Advanced features
553.5.1. Management553.5.1. Management
563.5.2. System-specific capabilities563.5.2. System-specific capabilities
diff --git a/doc/management.txt b/doc/management.txt
index 56e4f66..56f119e 100644
--- a/doc/management.txt
+++ b/doc/management.txt
@@ -2919,6 +2919,10 @@ show ssl crt-list [-n] [<filename>]
2919 ecdsa.pem:3 [verify none allow-0rtt ssl-min-ver TLSv1.0 ssl-max-ver TLSv1.3] localhost !www.test1.com2919 ecdsa.pem:3 [verify none allow-0rtt ssl-min-ver TLSv1.0 ssl-max-ver TLSv1.3] localhost !www.test1.com
2920 ecdsa.pem:4 [verify none allow-0rtt ssl-min-ver TLSv1.0 ssl-max-ver TLSv1.3]2920 ecdsa.pem:4 [verify none allow-0rtt ssl-min-ver TLSv1.0 ssl-max-ver TLSv1.3]
29212921
2922show startup-logs
2923 Dump all messages emitted during the startup of the current haproxy process,
2924 each startup-logs buffer is unique to its haproxy worker.
2925
2922show table2926show table
2923 Dump general information on all known stick-tables. Their name is returned2927 Dump general information on all known stick-tables. Their name is returned
2924 (the name of the proxy which holds them), their type (currently zero, always2928 (the name of the proxy which holds them), their type (currently zero, always
diff --git a/doc/proxy-protocol.txt b/doc/proxy-protocol.txt
index 4d49d5c..fac0331 100644
--- a/doc/proxy-protocol.txt
+++ b/doc/proxy-protocol.txt
@@ -500,7 +500,7 @@ protocol. Identifying the protocol version is easy :
500 - if the incoming byte count is 16 or above and the 13 first bytes match500 - if the incoming byte count is 16 or above and the 13 first bytes match
501 the protocol signature block followed by the protocol version 2 :501 the protocol signature block followed by the protocol version 2 :
502502
503 \x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A\x02503 \x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A\x20
504504
505 - otherwise, if the incoming byte count is 8 or above, and the 5 first505 - otherwise, if the incoming byte count is 8 or above, and the 5 first
506 characters match the US-ASCII representation of "PROXY" then the protocol506 characters match the US-ASCII representation of "PROXY" then the protocol
diff --git a/include/haproxy/buf.h b/include/haproxy/buf.h
index 6cfd9d3..fc7b6fb 100644
--- a/include/haproxy/buf.h
+++ b/include/haproxy/buf.h
@@ -445,7 +445,7 @@ static inline void b_slow_realign(struct buffer *b, char *swap, size_t output)
445445
446 /* process output data in two steps to cover wrapping */446 /* process output data in two steps to cover wrapping */
447 if (block1 > b_size(b) - b_head_ofs(b)) {447 if (block1 > b_size(b) - b_head_ofs(b)) {
448 block2 = b_size(b) - b_head_ofs(b);448 block2 = b_peek_ofs(b, block1);
449 block1 -= block2;449 block1 -= block2;
450 }450 }
451 memcpy(swap + b_size(b) - output, b_head(b), block1);451 memcpy(swap + b_size(b) - output, b_head(b), block1);
diff --git a/include/haproxy/bug.h b/include/haproxy/bug.h
index a2a9f6d..445dd7c 100644
--- a/include/haproxy/bug.h
+++ b/include/haproxy/bug.h
@@ -42,8 +42,10 @@ static inline __attribute((always_inline)) void ha_crash_now(void)
42#if __GNUC_PREREQ__(5, 0)42#if __GNUC_PREREQ__(5, 0)
43#pragma GCC diagnostic push43#pragma GCC diagnostic push
44#pragma GCC diagnostic ignored "-Warray-bounds"44#pragma GCC diagnostic ignored "-Warray-bounds"
45#if __GNUC_PREREQ__(6, 0)
45#pragma GCC diagnostic ignored "-Wnull-dereference"46#pragma GCC diagnostic ignored "-Wnull-dereference"
46#endif47#endif
48#endif
47 *(volatile char *)1 = 0;49 *(volatile char *)1 = 0;
48#if __GNUC_PREREQ__(5, 0)50#if __GNUC_PREREQ__(5, 0)
49#pragma GCC diagnostic pop51#pragma GCC diagnostic pop
diff --git a/include/haproxy/http.h b/include/haproxy/http.h
index d0f3fd2..8a86cb6 100644
--- a/include/haproxy/http.h
+++ b/include/haproxy/http.h
@@ -36,6 +36,8 @@ extern const uint8_t http_char_classes[256];
36enum http_meth_t find_http_meth(const char *str, const int len);36enum http_meth_t find_http_meth(const char *str, const int len);
37int http_get_status_idx(unsigned int status);37int http_get_status_idx(unsigned int status);
38const char *http_get_reason(unsigned int status);38const char *http_get_reason(unsigned int status);
39struct ist http_get_host_port(const struct ist host);
40int http_is_default_port(const struct ist schm, const struct ist port);
39int http_validate_scheme(const struct ist schm);41int http_validate_scheme(const struct ist schm);
40struct ist http_get_scheme(const struct ist uri);42struct ist http_get_scheme(const struct ist uri);
41struct ist http_get_authority(const struct ist uri, int no_userinfo);43struct ist http_get_authority(const struct ist uri, int no_userinfo);
diff --git a/include/haproxy/listener-t.h b/include/haproxy/listener-t.h
index c350290..476e65a 100644
--- a/include/haproxy/listener-t.h
+++ b/include/haproxy/listener-t.h
@@ -156,12 +156,21 @@ struct ssl_bind_conf {
156#endif156#endif
157};157};
158158
159/*
160 * In OpenSSL 3.0.0, the biggest verify error code's value is 94 and on the
161 * latest 1.1.1 it already reaches 79 so we need to size the ca/crt-ignore-err
162 * arrays accordingly. If the max error code increases, the arrays might need to
163 * be resized.
164 */
165#define SSL_MAX_VFY_ERROR_CODE 94
166#define IGNERR_BF_SIZE ((SSL_MAX_VFY_ERROR_CODE >> 6) + 1)
167
159/* "bind" line settings */168/* "bind" line settings */
160struct bind_conf {169struct bind_conf {
161#ifdef USE_OPENSSL170#ifdef USE_OPENSSL
162 struct ssl_bind_conf ssl_conf; /* ssl conf for ctx setting */171 struct ssl_bind_conf ssl_conf; /* ssl conf for ctx setting */
163 unsigned long long ca_ignerr; /* ignored verify errors in handshake if depth > 0 */172 unsigned long long ca_ignerr_bitfield[IGNERR_BF_SIZE]; /* ignored verify errors in handshake if depth > 0 */
164 unsigned long long crt_ignerr; /* ignored verify errors in handshake if depth == 0 */173 unsigned long long crt_ignerr_bitfield[IGNERR_BF_SIZE]; /* ignored verify errors in handshake if depth == 0 */
165 SSL_CTX *initial_ctx; /* SSL context for initial negotiation */174 SSL_CTX *initial_ctx; /* SSL context for initial negotiation */
166 SSL_CTX *default_ctx; /* SSL context of first/default certificate */175 SSL_CTX *default_ctx; /* SSL context of first/default certificate */
167 struct ssl_bind_conf *default_ssl_conf; /* custom SSL conf of default_ctx */176 struct ssl_bind_conf *default_ssl_conf; /* custom SSL conf of default_ctx */
diff --git a/include/haproxy/listener.h b/include/haproxy/listener.h
index 3fb078f..bb502c6 100644
--- a/include/haproxy/listener.h
+++ b/include/haproxy/listener.h
@@ -39,23 +39,29 @@ void listener_set_state(struct listener *l, enum li_state st);
39 * closes upon SHUT_WR and refuses to rebind. So a common validation path39 * closes upon SHUT_WR and refuses to rebind. So a common validation path
40 * involves SHUT_WR && listen && SHUT_RD. In case of success, the FD's polling40 * involves SHUT_WR && listen && SHUT_RD. In case of success, the FD's polling
41 * is disabled. It normally returns non-zero, unless an error is reported.41 * is disabled. It normally returns non-zero, unless an error is reported.
42 * It will need to operate under the proxy's lock. The caller is
43 * responsible for indicating in lpx whether the proxy locks is
44 * already held (non-zero) or not (zero) so that the function picks it.
42 */45 */
43int pause_listener(struct listener *l);46int pause_listener(struct listener *l, int lpx);
4447
45/* This function tries to resume a temporarily disabled listener.48/* This function tries to resume a temporarily disabled listener.
46 * The resulting state will either be LI_READY or LI_FULL. 0 is returned49 * The resulting state will either be LI_READY or LI_FULL. 0 is returned
47 * in case of failure to resume (eg: dead socket).50 * in case of failure to resume (eg: dead socket).
51 * It will need to operate under the proxy's lock. The caller is
52 * responsible for indicating in lpx whether the proxy locks is
53 * already held (non-zero) or not (zero) so that the function picks it.
48 */54 */
49int resume_listener(struct listener *l);55int resume_listener(struct listener *l, int lpx);
5056
51/*57/*
52 * This function completely stops a listener. It will need to operate under the58 * This function completely stops a listener. It will need to operate under the
53 * proxy's lock, the protocol's lock, and the listener's lock. The caller is59 * proxy's lock and the protocol's lock. The caller is
54 * responsible for indicating in lpx, lpr, lli whether the respective locks are60 * responsible for indicating in lpx, lpr whether the respective locks are
55 * already held (non-zero) or not (zero) so that the function picks the missing61 * already held (non-zero) or not (zero) so that the function picks the missing
56 * ones, in this order.62 * ones, in this order.
57 */63 */
58void stop_listener(struct listener *l, int lpx, int lpr, int lli);64void stop_listener(struct listener *l, int lpx, int lpr);
5965
60/* This function adds the specified listener's file descriptor to the polling66/* This function adds the specified listener's file descriptor to the polling
61 * lists if it is in the LI_LISTEN state. The listener enters LI_READY or67 * lists if it is in the LI_LISTEN state. The listener enters LI_READY or
diff --git a/include/haproxy/peers-t.h b/include/haproxy/peers-t.h
index ee9d905..93920fd 100644
--- a/include/haproxy/peers-t.h
+++ b/include/haproxy/peers-t.h
@@ -31,6 +31,7 @@
3131
32#include <haproxy/api-t.h>32#include <haproxy/api-t.h>
33#include <haproxy/dict-t.h>33#include <haproxy/dict-t.h>
34#include <haproxy/stick_table-t.h>
34#include <haproxy/thread-t.h>35#include <haproxy/thread-t.h>
3536
3637
diff --git a/include/haproxy/pool.h b/include/haproxy/pool.h
index 9264998..0547dcb 100644
--- a/include/haproxy/pool.h
+++ b/include/haproxy/pool.h
@@ -55,8 +55,8 @@ void pool_free_nocache(struct pool_head *pool, void *ptr);
55void dump_pools_to_trash();55void dump_pools_to_trash();
56void dump_pools(void);56void dump_pools(void);
57int pool_total_failures();57int pool_total_failures();
58unsigned long pool_total_allocated();58unsigned long long pool_total_allocated();
59unsigned long pool_total_used();59unsigned long long pool_total_used();
60void pool_flush(struct pool_head *pool);60void pool_flush(struct pool_head *pool);
61void pool_gc(struct pool_head *pool_ctx);61void pool_gc(struct pool_head *pool_ctx);
62struct pool_head *create_pool(char *name, unsigned int size, unsigned int flags);62struct pool_head *create_pool(char *name, unsigned int size, unsigned int flags);
diff --git a/include/haproxy/server.h b/include/haproxy/server.h
index c927de3..fdb285c 100644
--- a/include/haproxy/server.h
+++ b/include/haproxy/server.h
@@ -45,6 +45,7 @@ extern struct dict server_key_dict;
45int srv_downtime(const struct server *s);45int srv_downtime(const struct server *s);
46int srv_lastsession(const struct server *s);46int srv_lastsession(const struct server *s);
47int srv_getinter(const struct check *check);47int srv_getinter(const struct check *check);
48void srv_settings_cpy(struct server *srv, const struct server *src, int srv_tmpl);
48int parse_server(const char *file, int linenum, char **args, struct proxy *curproxy, const struct proxy *defproxy, int parse_flags);49int parse_server(const char *file, int linenum, char **args, struct proxy *curproxy, const struct proxy *defproxy, int parse_flags);
49int srv_update_addr(struct server *s, void *ip, int ip_sin_family, const char *updater);50int srv_update_addr(struct server *s, void *ip, int ip_sin_family, const char *updater);
50const char *srv_update_addr_port(struct server *s, const char *addr, const char *port, char *updater);51const char *srv_update_addr_port(struct server *s, const char *addr, const char *port, char *updater);
@@ -254,18 +255,21 @@ static inline enum srv_initaddr srv_get_next_initaddr(unsigned int *list)
254255
255static inline void srv_use_conn(struct server *srv, struct connection *conn)256static inline void srv_use_conn(struct server *srv, struct connection *conn)
256{257{
257 unsigned int curr;258 unsigned int curr, prev;
258259
259 curr = _HA_ATOMIC_ADD_FETCH(&srv->curr_used_conns, 1);260 curr = _HA_ATOMIC_ADD_FETCH(&srv->curr_used_conns, 1);
260261
262
261 /* It's ok not to do that atomically, we don't need an263 /* It's ok not to do that atomically, we don't need an
262 * exact max.264 * exact max.
263 */265 */
264 if (srv->max_used_conns < curr)266 prev = HA_ATOMIC_LOAD(&srv->max_used_conns);
265 srv->max_used_conns = curr;267 if (prev < curr)
268 HA_ATOMIC_STORE(&srv->max_used_conns, curr);
266269
267 if (srv->est_need_conns < curr)270 prev = HA_ATOMIC_LOAD(&srv->est_need_conns);
268 srv->est_need_conns = curr;271 if (prev < curr)
272 HA_ATOMIC_STORE(&srv->est_need_conns, curr);
269}273}
270274
271static inline void conn_delete_from_tree(struct ebmb_node *node)275static inline void conn_delete_from_tree(struct ebmb_node *node)
diff --git a/include/haproxy/sink.h b/include/haproxy/sink.h
index 51d507c..a9f8099 100644
--- a/include/haproxy/sink.h
+++ b/include/haproxy/sink.h
@@ -28,6 +28,8 @@
2828
29extern struct list sink_list;29extern struct list sink_list;
3030
31extern struct proxy *sink_proxies_list;
32
31struct sink *sink_find(const char *name);33struct sink *sink_find(const char *name);
32struct sink *sink_new_fd(const char *name, const char *desc, enum log_fmt, int fd);34struct sink *sink_new_fd(const char *name, const char *desc, enum log_fmt, int fd);
33ssize_t __sink_write(struct sink *sink, const struct ist msg[], size_t nmsg,35ssize_t __sink_write(struct sink *sink, const struct ist msg[], size_t nmsg,
diff --git a/include/haproxy/ssl_sock-t.h b/include/haproxy/ssl_sock-t.h
index 974b836..35270ca 100644
--- a/include/haproxy/ssl_sock-t.h
+++ b/include/haproxy/ssl_sock-t.h
@@ -52,16 +52,20 @@
52#define SSL_SOCK_SEND_UNLIMITED 0x0000000452#define SSL_SOCK_SEND_UNLIMITED 0x00000004
53#define SSL_SOCK_RECV_HEARTBEAT 0x0000000853#define SSL_SOCK_RECV_HEARTBEAT 0x00000008
5454
55/* bits 0xFFFF0000 are reserved to store verify errors */55/* bits 0xFFFFFF00 are reserved to store verify errors.
56 * The CA en CRT error codes will be stored on 7 bits each
57 * (since the max verify error code does not exceed 127)
58 * and the CA error depth will be stored on 4 bits.
59 */
5660
57/* Verify errors macros */61/* Verify errors macros */
58#define SSL_SOCK_CA_ERROR_TO_ST(e) (((e > 63) ? 63 : e) << (16))62#define SSL_SOCK_CA_ERROR_TO_ST(e) (((e > 127) ? 127 : e) << (8))
59#define SSL_SOCK_CAEDEPTH_TO_ST(d) (((d > 15) ? 15 : d) << (6+16))63#define SSL_SOCK_CAEDEPTH_TO_ST(d) (((d > 15) ? 15 : d) << (7+8))
60#define SSL_SOCK_CRTERROR_TO_ST(e) (((e > 63) ? 63 : e) << (4+6+16))64#define SSL_SOCK_CRTERROR_TO_ST(e) (((e > 127) ? 127 : e) << (4+7+8))
6165
62#define SSL_SOCK_ST_TO_CA_ERROR(s) ((s >> (16)) & 63)66#define SSL_SOCK_ST_TO_CA_ERROR(s) ((s >> (8)) & 127)
63#define SSL_SOCK_ST_TO_CAEDEPTH(s) ((s >> (6+16)) & 15)67#define SSL_SOCK_ST_TO_CAEDEPTH(s) ((s >> (7+8)) & 15)
64#define SSL_SOCK_ST_TO_CRTERROR(s) ((s >> (4+6+16)) & 63)68#define SSL_SOCK_ST_TO_CRTERROR(s) ((s >> (4+7+8)) & 127)
6569
66/* ssl_methods flags for ssl options */70/* ssl_methods flags for ssl options */
67#define MC_SSL_O_ALL 0x000071#define MC_SSL_O_ALL 0x0000
diff --git a/include/haproxy/ssl_sock.h b/include/haproxy/ssl_sock.h
index c68425a..9db4ec4 100644
--- a/include/haproxy/ssl_sock.h
+++ b/include/haproxy/ssl_sock.h
@@ -149,6 +149,29 @@ int ssl_sock_is_ssl(struct connection *conn)
149 return 1;149 return 1;
150}150}
151151
152static inline int cert_ignerr_bitfield_get(const unsigned long long *bitfield, int bit_index)
153{
154 int byte_index = bit_index >> 6;
155 int val = 0;
156
157 if (byte_index < IGNERR_BF_SIZE)
158 val = bitfield[byte_index] & (1ULL << (bit_index & 0x3F));
159
160 return val != 0;
161}
162
163static inline void cert_ignerr_bitfield_set(unsigned long long *bitfield, int bit_index)
164{
165 int byte_index = bit_index >> 6;
166
167 if (byte_index < IGNERR_BF_SIZE)
168 bitfield[byte_index] |= (1ULL << (bit_index & 0x3F));
169}
170
171static inline void cert_ignerr_bitfield_set_all(unsigned long long *bitfield)
172{
173 memset(bitfield, -1, IGNERR_BF_SIZE*sizeof(*bitfield));
174}
152175
153#endif /* USE_OPENSSL */176#endif /* USE_OPENSSL */
154#endif /* _HAPROXY_SSL_SOCK_H */177#endif /* _HAPROXY_SSL_SOCK_H */
diff --git a/include/haproxy/stats-t.h b/include/haproxy/stats-t.h
index 17641f5..920a311 100644
--- a/include/haproxy/stats-t.h
+++ b/include/haproxy/stats-t.h
@@ -443,7 +443,9 @@ enum stat_field {
443 ST_F_USED_CONN_CUR,443 ST_F_USED_CONN_CUR,
444 ST_F_NEED_CONN_EST,444 ST_F_NEED_CONN_EST,
445 ST_F_UWEIGHT,445 ST_F_UWEIGHT,
446 ST_F_AGG_SRV_STATUS,
446 ST_F_AGG_SRV_CHECK_STATUS,447 ST_F_AGG_SRV_CHECK_STATUS,
448 ST_F_AGG_CHECK_STATUS,
447449
448 /* must always be the last one */450 /* must always be the last one */
449 ST_F_TOTAL_FIELDS451 ST_F_TOTAL_FIELDS
diff --git a/include/haproxy/stream.h b/include/haproxy/stream.h
index 1ec87b1..5a61c20 100644
--- a/include/haproxy/stream.h
+++ b/include/haproxy/stream.h
@@ -337,7 +337,7 @@ static inline void stream_choose_redispatch(struct stream *s)
337 ((s->be->conn_retries - si->conn_retries) %337 ((s->be->conn_retries - si->conn_retries) %
338 (s->be->conn_retries + 1 + s->be->redispatch_after) == 0))) ||338 (s->be->conn_retries + 1 + s->be->redispatch_after) == 0))) ||
339 (!(s->flags & SF_DIRECT) && s->be->srv_act > 1 &&339 (!(s->flags & SF_DIRECT) && s->be->srv_act > 1 &&
340 ((s->be->lbprm.algo & BE_LB_KIND) == BE_LB_KIND_RR)))) {340 ((s->be->lbprm.algo & BE_LB_KIND) != BE_LB_KIND_HI)))) {
341 sess_change_server(s, NULL);341 sess_change_server(s, NULL);
342 if (may_dequeue_tasks(objt_server(s->target), s->be))342 if (may_dequeue_tasks(objt_server(s->target), s->be))
343 process_srv_queue(objt_server(s->target), 0);343 process_srv_queue(objt_server(s->target), 0);
diff --git a/include/haproxy/task.h b/include/haproxy/task.h
index d31c893..b3ffdf2 100644
--- a/include/haproxy/task.h
+++ b/include/haproxy/task.h
@@ -281,7 +281,7 @@ static inline struct task *task_unlink_wq(struct task *t)
281281
282 if (likely(task_in_wq(t))) {282 if (likely(task_in_wq(t))) {
283 locked = t->state & TASK_SHARED_WQ;283 locked = t->state & TASK_SHARED_WQ;
284 BUG_ON(!locked && t->thread_mask != tid_bit);284 BUG_ON(!locked && t->thread_mask != tid_bit && !(global.mode & MODE_STOPPING));
285 if (locked)285 if (locked)
286 HA_RWLOCK_WRLOCK(TASK_WQ_LOCK, &wq_lock);286 HA_RWLOCK_WRLOCK(TASK_WQ_LOCK, &wq_lock);
287 __task_unlink_wq(t);287 __task_unlink_wq(t);
@@ -526,6 +526,7 @@ static inline void tasklet_init(struct tasklet *t)
526 t->process = NULL;526 t->process = NULL;
527 t->tid = -1;527 t->tid = -1;
528#ifdef DEBUG_TASK528#ifdef DEBUG_TASK
529 t->call_date = 0;
529 t->debug.caller_idx = 0;530 t->debug.caller_idx = 0;
530#endif531#endif
531 LIST_INIT(&t->list);532 LIST_INIT(&t->list);
diff --git a/include/haproxy/tcpcheck-t.h b/include/haproxy/tcpcheck-t.h
index 29cb4cc..439fe18 100644
--- a/include/haproxy/tcpcheck-t.h
+++ b/include/haproxy/tcpcheck-t.h
@@ -35,6 +35,7 @@
35#define TCPCHK_OPT_DEFAULT_CONNECT 0x0008 /* Do a connect using server params */35#define TCPCHK_OPT_DEFAULT_CONNECT 0x0008 /* Do a connect using server params */
36#define TCPCHK_OPT_IMPLICIT 0x0010 /* Implicit connect */36#define TCPCHK_OPT_IMPLICIT 0x0010 /* Implicit connect */
37#define TCPCHK_OPT_SOCKS4 0x0020 /* check the connection via socks4 proxy */37#define TCPCHK_OPT_SOCKS4 0x0020 /* check the connection via socks4 proxy */
38#define TCPCHK_OPT_HAS_DATA 0x0040 /* data should be sent after conncetion */
3839
39enum tcpcheck_send_type {40enum tcpcheck_send_type {
40 TCPCHK_SEND_UNDEF = 0, /* Send is not parsed. */41 TCPCHK_SEND_UNDEF = 0, /* Send is not parsed. */
diff --git a/include/haproxy/tools.h b/include/haproxy/tools.h
index a95844a..30b6bfa 100644
--- a/include/haproxy/tools.h
+++ b/include/haproxy/tools.h
@@ -406,7 +406,8 @@ char *encode_chunk(char *start, char *stop,
406406
407/*407/*
408 * Tries to prefix characters tagged in the <map> with the <escape>408 * Tries to prefix characters tagged in the <map> with the <escape>
409 * character. The input <string> must be zero-terminated. The result will409 * character. The input <string> is processed until string_stop
410 * is reached or NULL-byte is encountered. The result will
410 * be stored between <start> (included) and <stop> (excluded). This411 * be stored between <start> (included) and <stop> (excluded). This
411 * function will always try to terminate the resulting string with a '\0'412 * function will always try to terminate the resulting string with a '\0'
412 * before <stop>, and will return its position if the conversion413 * before <stop>, and will return its position if the conversion
@@ -414,7 +415,7 @@ char *encode_chunk(char *start, char *stop,
414 */415 */
415char *escape_string(char *start, char *stop,416char *escape_string(char *start, char *stop,
416 const char escape, const long *map,417 const char escape, const long *map,
417 const char *string);418 const char *string, const char *string_stop);
418419
419/*420/*
420 * Tries to prefix characters tagged in the <map> with the <escape>421 * Tries to prefix characters tagged in the <map> with the <escape>
diff --git a/include/import/ebmbtree.h b/include/import/ebmbtree.h
index f99c16b..2d63ed1 100644
--- a/include/import/ebmbtree.h
+++ b/include/import/ebmbtree.h
@@ -118,6 +118,59 @@ struct ebmb_node *ebmb_lookup_longest(struct eb_root *root, const void *x);
118struct ebmb_node *ebmb_lookup_prefix(struct eb_root *root, const void *x, unsigned int pfx);118struct ebmb_node *ebmb_lookup_prefix(struct eb_root *root, const void *x, unsigned int pfx);
119struct ebmb_node *ebmb_insert_prefix(struct eb_root *root, struct ebmb_node *new, unsigned int len);119struct ebmb_node *ebmb_insert_prefix(struct eb_root *root, struct ebmb_node *new, unsigned int len);
120120
121/* start from a valid leaf and find the next matching prefix that's either a
122 * duplicate, or immediately shorter than the node's current one and still
123 * matches it. The purpose is to permit a caller that is not satisfied with a
124 * result provided by ebmb_lookup_longest() to evaluate the next matching
125 * entry. Given that shorter keys are necessarily attached to nodes located
126 * above the current one, it's sufficient to restart from the current leaf and
127 * go up until we find a shorter prefix, or a non-matching one.
128 */
129static inline struct ebmb_node *ebmb_lookup_shorter(struct ebmb_node *start)
130{
131 eb_troot_t *t = start->node.leaf_p;
132 struct ebmb_node *node;
133
134 /* first, chcek for duplicates */
135 node = ebmb_next_dup(start);
136 if (node)
137 return node;
138
139 while (1) {
140 if (eb_gettag(t) == EB_LEFT) {
141 /* Walking up from left branch. We must ensure that we never
142 * walk beyond root.
143 */
144 if (unlikely(eb_clrtag((eb_untag(t, EB_LEFT))->b[EB_RGHT]) == NULL))
145 return NULL;
146 node = container_of(eb_root_to_node(eb_untag(t, EB_LEFT)), struct ebmb_node, node);
147 } else {
148 /* Walking up from right branch, so we cannot be below
149 * root. However, if we end up on a node with an even
150 * and positive bit, this is a cover node, which mandates
151 * that the left branch only contains cover values, so we
152 * must descend it.
153 */
154 node = container_of(eb_root_to_node(eb_untag(t, EB_RGHT)), struct ebmb_node, node);
155 if (node->node.bit > 0 && !(node->node.bit & 1))
156 return ebmb_entry(eb_walk_down(t, EB_LEFT), struct ebmb_node, node);
157 }
158
159 /* Note that <t> cannot be NULL at this stage */
160 t = node->node.node_p;
161
162 /* this is a node attached to a deeper (and possibly different)
163 * leaf, not interesting for us.
164 */
165 if (node->node.pfx >= start->node.pfx)
166 continue;
167
168 if (check_bits(start->key, node->key, 0, node->node.pfx) == 0)
169 break;
170 }
171 return node;
172}
173
121/* The following functions are less likely to be used directly, because their174/* The following functions are less likely to be used directly, because their
122 * code is larger. The non-inlined version is preferred.175 * code is larger. The non-inlined version is preferred.
123 */176 */
diff --git a/reg-tests/cache/if-modified-since.vtc b/reg-tests/cache/if-modified-since.vtc
index 8ae1cce..387fc7e 100644
--- a/reg-tests/cache/if-modified-since.vtc
+++ b/reg-tests/cache/if-modified-since.vtc
@@ -62,6 +62,10 @@ haproxy h1 -conf {
62 server www ${s1_addr}:${s1_port}62 server www ${s1_addr}:${s1_port}
63 http-response cache-store my_cache63 http-response cache-store my_cache
6464
65 # Remove Transfer-Encoding header because of a vtest issue with
66 # 304-Not-Modified responses
67 http-after-response del-header transfer-encoding if { status eq 304 }
68
65 cache my_cache69 cache my_cache
66 total-max-size 370 total-max-size 3
67 max-age 2071 max-age 20
@@ -149,4 +153,3 @@ client c1 -connect ${h1_fe_sock} {
149 expect resp.bodylen == 0153 expect resp.bodylen == 0
150154
151} -run155} -run
152
diff --git a/reg-tests/cache/if-none-match.vtc b/reg-tests/cache/if-none-match.vtc
index ba3336a..bc7d67b 100644
--- a/reg-tests/cache/if-none-match.vtc
+++ b/reg-tests/cache/if-none-match.vtc
@@ -47,6 +47,10 @@ haproxy h1 -conf {
47 server www ${s1_addr}:${s1_port}47 server www ${s1_addr}:${s1_port}
48 http-response cache-store my_cache48 http-response cache-store my_cache
4949
50 # Remove Transfer-Encoding header because of a vtest issue with
51 # 304-Not-Modified responses
52 http-after-response del-header transfer-encoding if { status eq 304 }
53
50 cache my_cache54 cache my_cache
51 total-max-size 355 total-max-size 3
52 max-age 2056 max-age 20
diff --git a/reg-tests/checks/4be_1srv_smtpchk_httpchk_layer47errors.vtc b/reg-tests/checks/4be_1srv_smtpchk_httpchk_layer47errors.vtc
index f9f37a1..ea72701 100644
--- a/reg-tests/checks/4be_1srv_smtpchk_httpchk_layer47errors.vtc
+++ b/reg-tests/checks/4be_1srv_smtpchk_httpchk_layer47errors.vtc
@@ -8,7 +8,7 @@ barrier b cond 3
88
9syslog S1 -level notice {9syslog S1 -level notice {
10 recv10 recv
11 expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be1/srv1 succeeded.+reason: Layer7 check passed.+code: 2(20|48).+check duration: [[:digit:]]+ms.+status: 1/1 UP."11 expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be1/srv1 succeeded.+reason: Layer7 check passed.+code: 221.+check duration: [[:digit:]]+ms.+status: 1/1 UP."
12 barrier b sync12 barrier b sync
13 recv13 recv
14 expect ~ "Health check for server be1/srv1 failed.+reason: Layer7 timeout.+check duration: [[:digit:]]+ms.+status: 0/1 DOWN"14 expect ~ "Health check for server be1/srv1 failed.+reason: Layer7 timeout.+check duration: [[:digit:]]+ms.+status: 0/1 DOWN"
@@ -36,12 +36,17 @@ server s1 {
36 send "2"36 send "2"
37 send "2"37 send "2"
38 send "0"38 send "0"
39 send "\r\n\r\n"39 send "\r\n"
40 recv 1640 recv 16
41 send "2"41 send "2"
42 send "4"42 send "4"
43 send "8"43 send "8"
44 send "\r\n\r\n"44 send "\r\n"
45 recv 6
46 send "2"
47 send "2"
48 send "1"
49 send " ok\r\n"
45} -start50} -start
4651
47server s2 {52server s2 {
diff --git a/reg-tests/checks/pgsql-check.vtc b/reg-tests/checks/pgsql-check.vtc
index 968a18c..05c5a71 100644
--- a/reg-tests/checks/pgsql-check.vtc
+++ b/reg-tests/checks/pgsql-check.vtc
@@ -23,6 +23,11 @@ server s3 {
23 send "Not a PostgreSQL response"23 send "Not a PostgreSQL response"
24} -start24} -start
2525
26server s4 {
27 recv 23
28 sendhex "52000000170000000A534352414D2D5348412D3235360000"
29} -start
30
26syslog S1 -level notice {31syslog S1 -level notice {
27 recv32 recv
28 expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be1/srv succeeded, reason: Layer7 check passed.+info: \"PostgreSQL server is ok\".+check duration: [[:digit:]]+ms, status: 1/1 UP."33 expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be1/srv succeeded, reason: Layer7 check passed.+info: \"PostgreSQL server is ok\".+check duration: [[:digit:]]+ms, status: 1/1 UP."
@@ -38,6 +43,10 @@ syslog S3 -level notice {
38 expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be3/srv failed, reason: Layer7 wrong status.+info: \"PostgreSQL unknown error\".+check duration: [[:digit:]]+ms, status: 0/1 DOWN."43 expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be3/srv failed, reason: Layer7 wrong status.+info: \"PostgreSQL unknown error\".+check duration: [[:digit:]]+ms, status: 0/1 DOWN."
39} -start44} -start
4045
46syslog S4 -level notice {
47 recv
48 expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be4/srv succeeded, reason: Layer7 check passed.+info: \"PostgreSQL server is ok\".+check duration: [[:digit:]]+ms, status: 1/1 UP."
49} -start
4150
42haproxy h1 -conf {51haproxy h1 -conf {
43 defaults52 defaults
@@ -64,6 +73,12 @@ haproxy h1 -conf {
64 option pgsql-check user postgres73 option pgsql-check user postgres
65 server srv ${s3_addr}:${s3_port} check inter 1s rise 1 fall 174 server srv ${s3_addr}:${s3_port} check inter 1s rise 1 fall 1
6675
76 backend be4
77 log ${S4_addr}:${S4_port} daemon
78 option log-health-checks
79 option pgsql-check user postgres
80 server srv ${s4_addr}:${s4_port} check inter 1s rise 1 fall 1
81
67 listen pgsql182 listen pgsql1
68 bind "fd@${pgsql}"83 bind "fd@${pgsql}"
69 tcp-request inspect-delay 100ms84 tcp-request inspect-delay 100ms
@@ -75,3 +90,4 @@ haproxy h1 -conf {
75syslog S1 -wait90syslog S1 -wait
76syslog S2 -wait91syslog S2 -wait
77syslog S3 -wait92syslog S3 -wait
93syslog S4 -wait
diff --git a/reg-tests/checks/smtp-check.vtc b/reg-tests/checks/smtp-check.vtc
index 29d0ddb..9d8bb8a 100644
--- a/reg-tests/checks/smtp-check.vtc
+++ b/reg-tests/checks/smtp-check.vtc
@@ -10,6 +10,8 @@ server s1 {
10 send "220 smtp-check.vtc SMTP Server\r\n"10 send "220 smtp-check.vtc SMTP Server\r\n"
11 recv 1611 recv 16
12 send "250 smtp-check.vtc\r\n"12 send "250 smtp-check.vtc\r\n"
13 recv 6
14 send "221 smtp-check.vtc closing\r\n"
13} -start15} -start
1416
15server s2 {17server s2 {
@@ -18,6 +20,8 @@ server s2 {
18 send "250-smtp-check.vtc\r\n"20 send "250-smtp-check.vtc\r\n"
19 send "250-KEYWORD\r\n"21 send "250-KEYWORD\r\n"
20 send "250 LAST KEYWORD\r\n"22 send "250 LAST KEYWORD\r\n"
23 recv 6
24 send "221 smtp-check.vtc closing\r\n"
21} -start25} -start
2226
23server s3 {27server s3 {
@@ -36,12 +40,12 @@ server s5 {
3640
37syslog S1 -level notice {41syslog S1 -level notice {
38 recv42 recv
39 expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be1/srv succeeded, reason: Layer7 check passed.+code: 250.+info: \"smtp-check.vtc\".+check duration: [[:digit:]]+ms, status: 1/1 UP."43 expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be1/srv succeeded, reason: Layer7 check passed.+code: 221.+info: \"smtp-check.vtc closing\".+check duration: [[:digit:]]+ms, status: 1/1 UP."
40} -start44} -start
4145
42syslog S2 -level notice {46syslog S2 -level notice {
43 recv47 recv
44 expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be2/srv succeeded, reason: Layer7 check passed.+code: 250.+info: \"smtp-check.vtc\".+check duration: [[:digit:]]+ms, status: 1/1 UP."48 expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be2/srv succeeded, reason: Layer7 check passed.+code: 221.+info: \"smtp-check.vtc closing\".+check duration: [[:digit:]]+ms, status: 1/1 UP."
45} -start49} -start
4650
47syslog S3 -level notice {51syslog S3 -level notice {
diff --git a/reg-tests/contrib/prometheus.vtc b/reg-tests/contrib/prometheus.vtc
index ebe0b87..766db47 100644
--- a/reg-tests/contrib/prometheus.vtc
+++ b/reg-tests/contrib/prometheus.vtc
@@ -8,12 +8,12 @@ feature ignore_unknown_macro
8server s1 {8server s1 {
9 rxreq9 rxreq
10 txresp10 txresp
11} -repeat 2 -start11} -start
1212
13server s2 {13server s2 {
14 rxreq14 rxreq
15 txresp15 txresp
16} -repeat 2 -start16} -start
1717
18haproxy h1 -conf {18haproxy h1 -conf {
19 defaults19 defaults
@@ -33,8 +33,9 @@ haproxy h1 -conf {
3333
34 backend be34 backend be
35 stick-table type ip size 1m expire 10s store http_req_rate(10s)35 stick-table type ip size 1m expire 10s store http_req_rate(10s)
36 option httpchk
36 server s1 ${s1_addr}:${s1_port}37 server s1 ${s1_addr}:${s1_port}
37 server s2 ${s2_addr}:${s2_port} check maxqueue 10 maxconn 12 pool-max-conn 4238 server s2 ${s2_addr}:${s2_port} check inter 5s maxqueue 10 maxconn 12 pool-max-conn 42
38} -start39} -start
3940
40client c1 -connect ${h1_stats_sock} {41client c1 -connect ${h1_stats_sock} {
diff --git a/reg-tests/converter/digest.vtc b/reg-tests/converter/digest.vtc
index a14f1cc..511daca 100644
--- a/reg-tests/converter/digest.vtc
+++ b/reg-tests/converter/digest.vtc
@@ -7,7 +7,7 @@ feature ignore_unknown_macro
77
8server s1 {8server s1 {
9 rxreq9 rxreq
10 txresp10 txresp -hdr "Connection: close"
11} -repeat 2 -start11} -repeat 2 -start
1212
13haproxy h1 -conf {13haproxy h1 -conf {
diff --git a/reg-tests/converter/hmac.vtc b/reg-tests/converter/hmac.vtc
index f9d9d35..391e04a 100644
--- a/reg-tests/converter/hmac.vtc
+++ b/reg-tests/converter/hmac.vtc
@@ -7,7 +7,7 @@ feature ignore_unknown_macro
77
8server s1 {8server s1 {
9 rxreq9 rxreq
10 txresp10 txresp -hdr "Connection: close"
11} -repeat 2 -start11} -repeat 2 -start
1212
13haproxy h1 -conf {13haproxy h1 -conf {
diff --git a/reg-tests/converter/iif.vtc b/reg-tests/converter/iif.vtc
index 22414e0..3a6d6a6 100644
--- a/reg-tests/converter/iif.vtc
+++ b/reg-tests/converter/iif.vtc
@@ -5,7 +5,7 @@ feature ignore_unknown_macro
55
6server s1 {6server s1 {
7 rxreq7 rxreq
8 txresp8 txresp -hdr "Connection: close"
9} -repeat 3 -start9} -repeat 3 -start
1010
11haproxy h1 -conf {11haproxy h1 -conf {
diff --git a/reg-tests/converter/json_query.vtc b/reg-tests/converter/json_query.vtc
index b420942..9db77eb 100644
--- a/reg-tests/converter/json_query.vtc
+++ b/reg-tests/converter/json_query.vtc
@@ -5,7 +5,7 @@ feature ignore_unknown_macro
55
6server s1 {6server s1 {
7 rxreq7 rxreq
8 txresp8 txresp -hdr "Connection: close"
9} -repeat 8 -start9} -repeat 8 -start
1010
11haproxy h1 -conf {11haproxy h1 -conf {
diff --git a/reg-tests/http-messaging/h1_host_normalization.vtc b/reg-tests/http-messaging/h1_host_normalization.vtc
12new file mode 10064412new file mode 100644
index 0000000..6ea32d2
--- /dev/null
+++ b/reg-tests/http-messaging/h1_host_normalization.vtc
@@ -0,0 +1,276 @@
1varnishtest "H1 authority validation and host normalizarion based on the scheme (rfc3982 6.3.2) or the method (connect)"
2
3#REQUIRE_VERSION=2.4
4feature ignore_unknown_macro
5
6syslog S1 -level info {
7 # C1
8 recv
9 expect ~ "^.* uri: GET http://toto:poue@hostname/c1 HTTP/1.1; host: {hostname}$"
10
11 # C2
12 recv
13 expect ~ "^.* uri: GET http://hostname:8080/c2 HTTP/1.1; host: {hostname:8080}$"
14
15 # C3
16 recv
17 expect ~ "^.* uri: GET https://hostname/c3 HTTP/1.1; host: {hostname}$"
18
19 # C4
20 recv
21 expect ~ "^.* uri: GET https://hostname:80/c4 HTTP/1.1; host: {hostname:80}$"
22
23 # C5
24 recv
25 expect ~ "^.* uri: CONNECT hostname:80 HTTP/1.1; host: {hostname}$"
26 recv
27 expect ~ "^.* uri: CONNECT hostname:80 HTTP/1.1; host: {hostname}$"
28
29 # C6
30 recv
31 expect ~ "^.* uri: CONNECT hostname:443 HTTP/1.1; host: {hostname}$"
32 recv
33 expect ~ "^.* uri: CONNECT hostname:443 HTTP/1.1; host: {hostname}$"
34
35 recv
36 expect ~ "^.* uri: CONNECT hostname:8443 HTTP/1.1; host: {hostname:8443}$"
37} -start
38
39haproxy h1 -conf {
40 defaults
41 mode http
42 timeout connect 1s
43 timeout client 1s
44 timeout server 1s
45
46 frontend fe
47 bind "fd@${fe}"
48
49 http-request capture req.hdr(host) len 512
50 log-format "uri: %r; host: %hr"
51 log ${S1_addr}:${S1_port} len 2048 local0 debug err
52
53 http-request return status 200
54} -start
55
56# default port 80 with http scheme => should be normalized
57# Be sure userinfo are skipped
58client c1 -connect ${h1_fe_sock} {
59 txreq \
60 -req "GET" \
61 -url "http://toto:poue@hostname:80/c1" \
62 -hdr "host: hostname:80"
63
64 rxresp
65 expect resp.status == 200
66} -run
67
68# port 8080 with http scheme => no normalization
69client c2 -connect ${h1_fe_sock} {
70 txreq \
71 -req "GET" \
72 -url "http://hostname:8080/c2" \
73 -hdr "host: hostname:8080"
74
75 rxresp
76 expect resp.status == 200
77} -run
78
79# default port 443 with https scheme => should be normalized
80client c3 -connect ${h1_fe_sock} {
81 txreq \
82 -req "GET" \
83 -url "https://hostname:443/c3" \
84 -hdr "host: hostname:443"
85
86 rxresp
87 expect resp.status == 200
88} -run
89
90# port 80 with https scheme => no normalization
91client c4 -connect ${h1_fe_sock} {
92 txreq \
93 -req "GET" \
94 -url "https://hostname:80/c4" \
95 -hdr "host: hostname:80"
96
97 rxresp
98 expect resp.status == 200
99} -run
100
101# CONNECT on port 80 => should be normalized
102client c5 -connect ${h1_fe_sock} {
103 txreq \
104 -req "CONNECT" \
105 -url "hostname:80" \
106 -hdr "host: hostname:80"
107
108 rxresp
109 expect resp.status == 200
110} -run
111client c5 -connect ${h1_fe_sock} {
112
113 txreq \
114 -req "CONNECT" \
115 -url "hostname:80" \
116 -hdr "host: hostname"
117
118 rxresp
119 expect resp.status == 200
120} -run
121
122# CONNECT on port 443 => should be normalized
123client c6 -connect ${h1_fe_sock} {
124 txreq \
125 -req "CONNECT" \
126 -url "hostname:443" \
127 -hdr "host: hostname:443"
128
129 rxresp
130 expect resp.status == 200
131} -run
132client c6 -connect ${h1_fe_sock} {
133 txreq \
134 -req "CONNECT" \
135 -url "hostname:443" \
136 -hdr "host: hostname"
137
138 rxresp
139 expect resp.status == 200
140} -run
141
142# CONNECT on port non-default port => no normalization
143client c7 -connect ${h1_fe_sock} {
144 txreq \
145 -req "CONNECT" \
146 -url "hostname:8443" \
147 -hdr "host: hostname:8443"
148
149 rxresp
150 expect resp.status == 200
151} -run
152
153# host miss-match => error
154client c8 -connect ${h1_fe_sock} {
155 txreq \
156 -req "GET" \
157 -url "http://hostname1/" \
158 -hdr "host: hostname2"
159
160 rxresp
161 expect resp.status == 400
162} -run
163
164# port miss-match => error
165client c9 -connect ${h1_fe_sock} {
166 txreq \
167 -req "GET" \
168 -url "http://hostname:80/" \
169 -hdr "host: hostname:81"
170
171 rxresp
172 expect resp.status == 400
173} -run
174
175# no host port with a non-default port in abs-uri => error
176client c10 -connect ${h1_fe_sock} {
177 txreq \
178 -req "GET" \
179 -url "http://hostname:8080/" \
180 -hdr "host: hostname"
181
182 rxresp
183 expect resp.status == 400
184} -run
185
186# non-default host port with a default in abs-uri => error
187client c11 -connect ${h1_fe_sock} {
188 txreq \
189 -req "GET" \
190 -url "http://hostname/" \
191 -hdr "host: hostname:81"
192
193 rxresp
194 expect resp.status == 400
195} -run
196
197# miss-match between host headers => error
198client c12 -connect ${h1_fe_sock} {
199 txreq \
200 -req "GET" \
201 -url "http://hostname1/" \
202 -hdr "host: hostname1" \
203 -hdr "host: hostname2"
204
205 rxresp
206 expect resp.status == 400
207} -run
208
209# miss-match between host headers but with a normalization => error
210client c13 -connect ${h1_fe_sock} {
211 txreq \
212 -req "GET" \
213 -url "http://hostname1/" \
214 -hdr "host: hostname1:80" \
215 -hdr "host: hostname1"
216
217 rxresp
218 expect resp.status == 400
219} -run
220
221# CONNECT authoriy without port => error
222client c14 -connect ${h1_fe_sock} {
223 txreq \
224 -req "CONNECT" \
225 -url "hostname" \
226 -hdr "host: hostname"
227
228 rxresp
229 expect resp.status == 400
230} -run
231
232# host miss-match with CONNECT => error
233client c15 -connect ${h1_fe_sock} {
234 txreq \
235 -req "CONNECT" \
236 -url "hostname1:80" \
237 -hdr "host: hostname2:80"
238
239 rxresp
240 expect resp.status == 400
241} -run
242
243# port miss-match with CONNECT => error
244client c16 -connect ${h1_fe_sock} {
245 txreq \
246 -req "CONNECT" \
247 -url "hostname:80" \
248 -hdr "host: hostname:443"
249
250 rxresp
251 expect resp.status == 400
252} -run
253
254# no host port with non-default port in CONNECT authority => error
255client c17 -connect ${h1_fe_sock} {
256 txreq \
257 -req "CONNECT" \
258 -url "hostname:8080" \
259 -hdr "host: hostname"
260
261 rxresp
262 expect resp.status == 400
263} -run
264
265# no authority => error
266client c18 -connect ${h1_fe_sock} {
267 txreq \
268 -req "CONNECT" \
269 -url "/" \
270 -hdr "host: hostname"
271
272 rxresp
273 expect resp.status == 400
274} -run
275
276syslog S1 -wait
diff --git a/reg-tests/http-messaging/http_request_buffer.vtc b/reg-tests/http-messaging/http_request_buffer.vtc
index f1cec1a..e712e32 100644
--- a/reg-tests/http-messaging/http_request_buffer.vtc
+++ b/reg-tests/http-messaging/http_request_buffer.vtc
@@ -9,6 +9,8 @@ feature ignore_unknown_macro
9# thanks to "http-buffer-request". If this was the case, c2 client9# thanks to "http-buffer-request". If this was the case, c2 client
10# could not connect to s1 server and this would lead to make this test fail.10# could not connect to s1 server and this would lead to make this test fail.
1111
12barrier b1 cond 2 -cyclic
13
12server s1 {14server s1 {
13 rxreq15 rxreq
14 expect req.bodylen == 25716 expect req.bodylen == 257
@@ -23,11 +25,17 @@ server s1 {
2325
24syslog S -level info {26syslog S -level info {
25 recv27 recv
26 expect ~ "[^:\\[ ]*\\[[0-9]*\\]: .* .* fe1 fe1/<NOSRV> .* 408 .* - - cD-- .* .* \"GET /this-is-a-long-url-this-is-a-long-url-this-is-a-long-url-this-is-a-long-url-this-is-a-long-url-this-is-a-long-url-this-is-a-long-url HTTP/1\\.1\""28 expect ~ "[^:\\[ ]*\\[[0-9]*\\]: .* .* fe1 fe1/<NOSRV> .* 408 .* - - cR-- .* .* \"GET /this-is-a-long-url-this-is-a-long-url-this-is-a-long-url-this-is-a-long-url-this-is-a-long-url-this-is-a-long-url-this-is-a-long-url HTTP/1\\.1\""
29 barrier b1 sync
30
27 recv31 recv
28 expect ~ "[^:\\[ ]*\\[[0-9]*\\]: .* .* fe1 be1/srv1 [0-9]*/[0-9]*/[0-9]*/[0-9]*/[0-9]* 200 .* - - ---- .* .* \"GET / HTTP/1\\.1\""32 expect ~ "[^:\\[ ]*\\[[0-9]*\\]: .* .* fe1 be1/srv1 [0-9]*/[0-9]*/[0-9]*/[0-9]*/[0-9]* 200 .* - - ---- .* .* \"GET / HTTP/1\\.1\""
33 barrier b1 sync
34
29 recv35 recv
30 expect ~ "[^:\\[ ]*\\[[0-9]*\\]: .* .* fe2 be1/srv1 [0-9]*/[0-9]*/[0-9]*/[0-9]*/[0-9]* 200 .* - - ---- .* .* \"POST /1 HTTP/1\\.1\""36 expect ~ "[^:\\[ ]*\\[[0-9]*\\]: .* .* fe2 be1/srv1 [0-9]*/[0-9]*/[0-9]*/[0-9]*/[0-9]* 200 .* - - ---- .* .* \"POST /1 HTTP/1\\.1\""
37 barrier b1 sync
38
31 recv39 recv
32 expect ~ "[^:\\[ ]*\\[[0-9]*\\]: .* .* fe2 be1/<NOSRV> [0-9]*/-1/-1/-1/[0-9]* -1 .* - - CR-- .* .* \"POST /2 HTTP/1\\.1\""40 expect ~ "[^:\\[ ]*\\[[0-9]*\\]: .* .* fe2 be1/<NOSRV> [0-9]*/-1/-1/-1/[0-9]* -1 .* - - CR-- .* .* \"POST /2 HTTP/1\\.1\""
33} -start41} -start
@@ -88,6 +96,9 @@ client c1 -connect ${h1_fe1_sock} {
88 expect resp.status == 40896 expect resp.status == 408
89} -run97} -run
9098
99# Wait matching on log message
100barrier b1 sync
101
91# Payload is fully sent102# Payload is fully sent
92# ==> Request must be sent to the server. A 200 must be received103# ==> Request must be sent to the server. A 200 must be received
93client c2 -connect ${h1_fe1_sock} {104client c2 -connect ${h1_fe1_sock} {
@@ -96,6 +107,9 @@ client c2 -connect ${h1_fe1_sock} {
96 expect resp.status == 200107 expect resp.status == 200
97} -run108} -run
98109
110# Wait matching on log message
111barrier b1 sync
112
99# Payload is fully sent in 2 steps (with a small delay, smaller than the client113# Payload is fully sent in 2 steps (with a small delay, smaller than the client
100# timeout) and splitted on a chunk size.114# timeout) and splitted on a chunk size.
101# ==> Request must be sent to the server. A 200 must be received115# ==> Request must be sent to the server. A 200 must be received
@@ -107,6 +121,9 @@ client c3 -connect ${h1_fe2_sock} {
107 expect resp.status == 200121 expect resp.status == 200
108} -run122} -run
109123
124# Wait matching on log message
125barrier b1 sync
126
110# Last CRLF of the request payload is missing but payload is sent in 2 steps127# Last CRLF of the request payload is missing but payload is sent in 2 steps
111# (with a small delay, smaller than the client timeout) and splitted on a chunk128# (with a small delay, smaller than the client timeout) and splitted on a chunk
112# size. The client aborts before sending the last CRLF.129# size. The client aborts before sending the last CRLF.
diff --git a/reg-tests/http-rules/restrict_req_hdr_names.vtc b/reg-tests/http-rules/restrict_req_hdr_names.vtc
index 57bc7e1..b493c84 100644
--- a/reg-tests/http-rules/restrict_req_hdr_names.vtc
+++ b/reg-tests/http-rules/restrict_req_hdr_names.vtc
@@ -35,6 +35,32 @@ server s5 {
35 txresp35 txresp
36} -start36} -start
3737
38server s6 {
39 rxreq
40 expect req.http.x_my_hdr_with_lots_of_underscores == <undef>
41 txresp
42} -start
43
44server s7 {
45 rxreq
46 expect req.http.x_my_hdr-1 == <undef>
47 expect req.http.x-my-hdr-2 == on
48 txresp
49} -start
50
51server s8 {
52 rxreq
53 expect req.http.x-my_hdr-1 == <undef>
54 expect req.http.x-my_hdr-2 == <undef>
55 txresp
56} -start
57
58server s9 {
59 rxreq
60 expect req.http.x-my-hdr-with-trailing-underscore_ == <undef>
61 txresp
62} -start
63
38haproxy h1 -conf {64haproxy h1 -conf {
39 defaults65 defaults
40 mode http66 mode http
@@ -50,6 +76,10 @@ haproxy h1 -conf {
50 use_backend be-fcgi1 if { path /req4 }76 use_backend be-fcgi1 if { path /req4 }
51 use_backend be-fcgi2 if { path /req5 }77 use_backend be-fcgi2 if { path /req5 }
52 use_backend be-fcgi3 if { path /req6 }78 use_backend be-fcgi3 if { path /req6 }
79 use_backend be-http4 if { path /req7 }
80 use_backend be-http5 if { path /req8 }
81 use_backend be-http6 if { path /req9 }
82 use_backend be-http7 if { path /req10 }
5383
54 backend be-http184 backend be-http1
55 server s1 ${s1_addr}:${s1_port}85 server s1 ${s1_addr}:${s1_port}
@@ -72,6 +102,22 @@ haproxy h1 -conf {
72 backend be-fcgi3102 backend be-fcgi3
73 option http-restrict-req-hdr-names reject103 option http-restrict-req-hdr-names reject
74104
105 backend be-http4
106 option http-restrict-req-hdr-names delete
107 server s6 ${s6_addr}:${s6_port}
108
109 backend be-http5
110 option http-restrict-req-hdr-names delete
111 server s7 ${s7_addr}:${s7_port}
112
113 backend be-http6
114 option http-restrict-req-hdr-names delete
115 server s8 ${s8_addr}:${s8_port}
116
117 backend be-http7
118 option http-restrict-req-hdr-names delete
119 server s9 ${s9_addr}:${s9_port}
120
75 defaults121 defaults
76 mode http122 mode http
77 timeout connect 1s123 timeout connect 1s
@@ -114,6 +160,22 @@ client c1 -connect ${h1_fe1_sock} {
114 txreq -req GET -url /req6 -hdr "X-my_hdr: on"160 txreq -req GET -url /req6 -hdr "X-my_hdr: on"
115 rxresp161 rxresp
116 expect resp.status == 403162 expect resp.status == 403
163
164 txreq -req GET -url /req7 -hdr "X_my_hdr_with_lots_of_underscores: on"
165 rxresp
166 expect resp.status == 200
167
168 txreq -req GET -url /req8 -hdr "X_my_hdr-1: on" -hdr "X-my-hdr-2: on"
169 rxresp
170 expect resp.status == 200
171
172 txreq -req GET -url /req9 -hdr "X-my_hdr-1: on" -hdr "X-my_hdr-2: on"
173 rxresp
174 expect resp.status == 200
175
176 txreq -req GET -url /req10 -hdr "X-my-hdr-with-trailing-underscore_: on"
177 rxresp
178 expect resp.status == 200
117} -run179} -run
118180
119client c2 -connect ${h1_fe2_sock} {181client c2 -connect ${h1_fe2_sock} {
diff --git a/reg-tests/log/log_forward.vtc b/reg-tests/log/log_forward.vtc
120new file mode 100644182new file mode 100644
index 0000000..3977f4c
--- /dev/null
+++ b/reg-tests/log/log_forward.vtc
@@ -0,0 +1,57 @@
1varnishtest "Test the TCP load-forward"
2feature cmd "$HAPROXY_PROGRAM -cc 'version_atleast(2.3-dev1)'"
3feature ignore_unknown_macro
4
5server s1 {
6 rxreq
7 txresp
8} -repeat 500 -start
9
10syslog Slg1 -level info {
11 recv
12 expect ~ "[^:\\[ ]\\[${h1_pid}\\]: .* \"GET /client_c1 HTTP/1.1\""
13} -repeat 50 -start
14
15haproxy h1 -conf {
16 defaults
17 mode http
18 option httplog
19 timeout connect "${HAPROXY_TEST_TIMEOUT-5s}"
20 timeout client "${HAPROXY_TEST_TIMEOUT-5s}"
21 timeout server "${HAPROXY_TEST_TIMEOUT-5s}"
22
23 frontend fe1
24 bind "fd@${fe_1}"
25 log 127.0.0.1:1514 local0
26# log ${Slg1_addr}:${Slg1_port} local0
27 default_backend be
28
29 backend be
30 server app1 ${s1_addr}:${s1_port}
31
32 ring myring
33 description "My local buffer"
34 format rfc5424
35 maxlen 1200
36 size 32764
37 timeout connect 5s
38 timeout server 10s
39 # syslog tcp server
40 server mysyslogsrv 127.0.0.1:2514
41
42 log-forward syslog2tcp
43 dgram-bind 127.0.0.1:1514
44 log ring@myring local0 # To TCP log
45
46 log-forward syslog2local
47 bind 127.0.0.1:2514
48 log ${Slg1_addr}:${Slg1_port} local0 # To VTest syslog
49} -start
50
51client c1 -connect ${h1_fe_1_sock} {
52 txreq -url "/client_c1"
53 rxresp
54 expect resp.status == 200
55} -repeat 50 -start
56
57syslog Slg1 -wait
diff --git a/reg-tests/mailers/healthcheckmail.vtc b/reg-tests/mailers/healthcheckmail.vtc
index 43bf588..d36a0d3 100644
--- a/reg-tests/mailers/healthcheckmail.vtc
+++ b/reg-tests/mailers/healthcheckmail.vtc
@@ -5,7 +5,7 @@ feature ignore_unknown_macro
55
6syslog S1 -level notice {6syslog S1 -level notice {
7 recv7 recv
8 expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be1/srv1 failed.+reason: Socket error.+info: \".+\".+check duration: [[:digit:]]+ms.+status: 0/1 DOWN."8 expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be1/srv1 failed.+check duration: [[:digit:]]+ms.+status: 0/1 DOWN."
9 recv info9 recv info
10 expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Result=SUCCESS Bytes=[[:digit:]]+"10 expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Result=SUCCESS Bytes=[[:digit:]]+"
11} -start11} -start
diff --git a/reg-tests/ssl/log_forward_ssl.vtc b/reg-tests/ssl/log_forward_ssl.vtc
12new file mode 10064412new file mode 100644
index 0000000..6b7515b
--- /dev/null
+++ b/reg-tests/ssl/log_forward_ssl.vtc
@@ -0,0 +1,60 @@
1varnishtest "Test the TCP+SSL load-forward"
2feature cmd "$HAPROXY_PROGRAM -cc 'version_atleast(2.3-dev1)'"
3feature cmd "$HAPROXY_PROGRAM -cc 'feature(OPENSSL)'"
4feature ignore_unknown_macro
5
6server s1 {
7 rxreq
8 txresp
9} -repeat 500 -start
10
11syslog Slg1 -level info {
12 recv
13 expect ~ "[^:\\[ ]\\[${h1_pid}\\]: .* \"GET /client_c1 HTTP/1.1\""
14} -repeat 50 -start
15
16haproxy h1 -conf {
17 global
18 insecure-fork-wanted
19 defaults
20 mode http
21 option httplog
22 timeout connect "${HAPROXY_TEST_TIMEOUT-5s}"
23 timeout client "${HAPROXY_TEST_TIMEOUT-5s}"
24 timeout server "${HAPROXY_TEST_TIMEOUT-5s}"
25
26 frontend fe1
27 bind "fd@${fe_1}"
28 log 127.0.0.1:1514 local0
29# log ${Slg1_addr}:${Slg1_port} local0
30 default_backend be
31
32 backend be
33 server app1 ${s1_addr}:${s1_port}
34
35 ring myring
36 description "My local buffer"
37 format rfc5424
38 maxlen 1200
39 size 32764
40 timeout connect 5s
41 timeout server 10s
42 # syslog tcp server
43 server mysyslogsrv 127.0.0.1:2514 ssl verify none
44
45 log-forward syslog2tcp
46 dgram-bind 127.0.0.1:1514
47 log ring@myring local0 # To TCP log
48
49 log-forward syslog2local
50 bind 127.0.0.1:2514 ssl crt ${testdir}/common.pem
51 log ${Slg1_addr}:${Slg1_port} local0 # To VTest syslog
52} -start
53
54client c1 -connect ${h1_fe_1_sock} {
55 txreq -url "/client_c1"
56 rxresp
57 expect resp.status == 200
58} -repeat 50 -start
59
60syslog Slg1 -wait
diff --git a/reg-tests/startup/automatic_maxconn.vtc b/reg-tests/startup/automatic_maxconn.vtc
0new file mode 10064461new file mode 100644
index 0000000..686a5c5
--- /dev/null
+++ b/reg-tests/startup/automatic_maxconn.vtc
@@ -0,0 +1,102 @@
1#REGTEST_TYPE=broken
2#REQUIRE_VERSION=2.2
3#REQUIRE_OPTION=OPENSSL
4
5# Check the maxconn computation with the -m parameter
6# Broken because it can't work with ASAN.
7
8varnishtest "Automatic maxconn computation"
9
10
11feature ignore_unknown_macro
12
13server s1 {
14 rxreq
15 txresp
16} -start
17
18
19haproxy h1 -arg "-m 1024" -conf {
20} -start
21
22haproxy h1 -cli {
23 send "show info"
24 expect ~ ".*Maxconn: 29000\n.*"
25}
26
27haproxy h2 -arg "-m 384" -conf {
28} -start
29
30haproxy h2 -cli {
31 send "show info"
32 expect ~ ".*Maxconn: 10000\n.*"
33}
34
35haproxy h3 -arg "-m 256" -conf {
36} -start
37
38haproxy h3 -cli {
39 send "show info"
40 expect ~ ".*Maxconn: 7300\n.*"
41}
42
43# 1 SSL front but no back
44
45haproxy h4 -arg "-m 256" -conf {
46 defaults
47 mode http
48 timeout connect 1s
49 timeout client 1s
50 timeout server 1s
51
52 frontend fe1
53 bind "fd@${fe1}" ssl crt ${testdir}/common.pem
54
55} -start
56
57haproxy h4 -cli {
58 send "show info"
59 expect ~ ".*Maxconn: 1900\n.*"
60}
61
62# 1 SSL back but not front
63
64haproxy h5 -arg "-m 256" -conf {
65 defaults
66 mode http
67 timeout connect 1s
68 timeout client 1s
69 timeout server 1s
70
71 listen li2
72 bind "fd@${li2}"
73 server ssl "${s1_addr}:${s1_port}" ssl verify none
74
75} -start
76
77haproxy h5 -cli {
78 send "show info"
79 expect ~ ".*Maxconn: 1900\n.*"
80}
81
82
83# 1 SSL front and 1 back
84
85haproxy h6 -arg "-m 256" -conf {
86 defaults
87 mode http
88 timeout connect 1s
89 timeout client 1s
90 timeout server 1s
91
92 listen li3
93 bind "fd@${li3}" ssl crt ${testdir}/common.pem
94 server ssl "${s1_addr}:${s1_port}" ssl verify none
95
96} -start
97
98haproxy h6 -cli {
99 send "show info"
100 expect ~ ".*Maxconn: 1700\n.*"
101}
102
diff --git a/reg-tests/startup/common.pem b/reg-tests/startup/common.pem
0new file mode 100644103new file mode 100644
index 0000000..206e417
--- /dev/null
+++ b/reg-tests/startup/common.pem
@@ -0,0 +1,117 @@
1-----BEGIN RSA PRIVATE KEY-----
2MIIEpAIBAAKCAQEAnb0BDF7FsqzslakNg7u/n/JQkq6nheuKwvyTqECfpc9y7uSB
3e/vrEFqBaDSLQagJxuZdL5geFeVtRbdAoB97N1/LZa6vecjjgGSP0Aag/gS/ocnM
4RIyvlVWWT9MrD46OG3qZY1ORU1ltrVL0NKttJP8xME7j3bTwIDElx/hNI0n7L+yS
5kAe2xb/7CbZRfoOhjTVAcGv4aSLVc/Hi8k6VkIzdOEtH6TcghXmuGcuqvLNH9Buo
6syngKTcQ8zg6J+e64aVvC+e7vi94uil9Qu+JHm0pkDzAZ2WluNsuXlrJToPirWyj
76/YdN6xgSI1hbZkBmUPAebgYuxBt6huvfyQd3wIDAQABAoIBABojc8UE/2W4WgwC
804Z82ig7Ezb7Ui9S9M+S4zUCYHItijIkE4DkIfO3y7Hk4x6iJdyb191HK9UdC5p9
932upS9XFPgM/izx3GZvxDhO+xXbSep7ovbyuQ3pPkHTx3TTavpm3GyvmcTKKoy4R
10jP4dWhzDXPdQW1ol3ZS4EDau4rlyClY6oi1mq9aBEX3MqVjB/nO7s2AbdgclAgP2
11OZMhTzWYR1k5tYySHCXh3ggGMCikyvHU0+SsGyrstYzP1VYi/n3f0VgqW/5ZjG8x
126SHpe04unErPF3HuSun2ZMCFdBxaTFZ8FENb8evrSXe3nQOc9W21RQdRRrNNUbjl
13JYI4veECgYEA0ATYKMS1VCUYRZoQ49b5GTg7avUYqfW4bEo4fSfBue8NrnKR3Wu8
14PPBiCTuIYq1vSF+60B7Vu+hW0A8OuQ2UuMxLpYcQ7lKfNad/+yAfoWWafIqCqNU9
15at0QMdbW6A69d6jZt7OrXtleBsphCnN58jTz4ch4PIa2Oyq46NUXCvUCgYEAwh8t
16G6BOHOs3yRNI2s9Y9EEfwoil2uIKrZhqiL3AwdIpu5uNIMuPnbaEpXvRX6jv/qtL
17321i8vZLc31aM7zfxQ6B4ReQFJfYC80FJsWvcLwT9hB9mTJpLS4sIu5tzQc87O6w
18RtjFMom+5ns5hfPB4Eccy0EtbQWVY4nCzUeO6QMCgYBSvqqRRPXwG7VU8lznlHqP
19upuABzChYrnScY+Y0TixUlL54l79Wb6N6vzEOWceAWkzu8iewrU4QspNhr/PgoR3
20IeSxWlG0yy7Dc/ZnmTabx8O06I/iwrfkizzG5nOj6UEamRLJjPGNEB/jyZriQl7u
21pnugg1K4mMliLbNSAnlhBQKBgQCmYepbv260Qrex1KGhSg9Ia3k5V74weYYFfJnz
22UhChD+1NK+ourcsOtp3C6PlwMHBjq5aAjlU9QfUxq8NgjQaO8/xGXdfUjsFSfAtq
23TA4vZkUFpuTAJgEYBHc4CXx7OzTxLzRPxQRgaMgC7KNFOMR34vu/CsJQq3R7uFwL
24bsYC2QKBgQCtEmg1uDZVdByX9zyUMuRxz5Tq/vDcp+A5lJj2mha1+bUMaKX2+lxQ
25vPxY55Vaw/ukWkJirRrpGv6IytBn0dLAFSlKZworZGBaxsm8OGTFJ5Oe9+kZTjI9
26hvjpClOA1otbmj2F2uZAbuIjxQGDNUkLoifN5yDYCC8JPujHuHmULw==
27-----END RSA PRIVATE KEY-----
28-----BEGIN CERTIFICATE-----
29MIIGeTCCBGGgAwIBAgIBAjANBgkqhkiG9w0BAQsFADB+MQswCQYDVQQGEwJGUjEW
30MBQGA1UECBMNSWxlLWRlLUZyYW5jZTEOMAwGA1UEBxMFUGFyaXMxEDAOBgNVBAoT
31B296b24uaW8xFTATBgNVBAMTDE96b24gVGVzdCBDQTEeMBwGCSqGSIb3DQEJARYP
32c3VwcG9ydEBvem9uLmlvMB4XDTE2MDExNzIzMDIzOFoXDTE4MDExNjIzMDIzOFow
33gb4xCzAJBgNVBAYTAkZSMRYwFAYDVQQIEw1JbGUtZGUtRnJhbmNlMRowGAYDVQQH
34ExFOZXVpbGx5LXN1ci1TZWluZTEYMBYGA1UEChMPVE9BRCBDb25zdWx0aW5nMRcw
35FQYDVQQLEw5lUGFyYXBoZXIgVGVhbTEWMBQGA1UEAxMNd3d3LnRlc3QxLmNvbTEw
36MC4GCSqGSIb3DQEJARYhYXJuYXVsdC5taWNoZWxAdG9hZC1jb25zdWx0aW5nLmZy
37MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnb0BDF7FsqzslakNg7u/
38n/JQkq6nheuKwvyTqECfpc9y7uSBe/vrEFqBaDSLQagJxuZdL5geFeVtRbdAoB97
39N1/LZa6vecjjgGSP0Aag/gS/ocnMRIyvlVWWT9MrD46OG3qZY1ORU1ltrVL0NKtt
40JP8xME7j3bTwIDElx/hNI0n7L+ySkAe2xb/7CbZRfoOhjTVAcGv4aSLVc/Hi8k6V
41kIzdOEtH6TcghXmuGcuqvLNH9BuosyngKTcQ8zg6J+e64aVvC+e7vi94uil9Qu+J
42Hm0pkDzAZ2WluNsuXlrJToPirWyj6/YdN6xgSI1hbZkBmUPAebgYuxBt6huvfyQd
433wIDAQABo4IBvzCCAbswCwYDVR0PBAQDAgOoMBMGA1UdJQQMMAoGCCsGAQUFBwMB
44MB0GA1UdDgQWBBTIihFNVNgOseQnsWEcAQxAbIKE4TCBsgYDVR0jBIGqMIGngBRv
45G9At9gzk2MW5Z7JVey1LtPIZ8KGBg6SBgDB+MQswCQYDVQQGEwJGUjEWMBQGA1UE
46CBMNSWxlLWRlLUZyYW5jZTEOMAwGA1UEBxMFUGFyaXMxEDAOBgNVBAoTB296b24u
47aW8xFTATBgNVBAMTDE96b24gVGVzdCBDQTEeMBwGCSqGSIb3DQEJARYPc3VwcG9y
48dEBvem9uLmlvggkA15FtIaGcrk8wDAYDVR0TAQH/BAIwADAaBgNVHREEEzARgg9j
49b21tb25OYW1lOmNvcHkwCQYDVR0SBAIwADBIBgNVHR8EQTA/MD2gO6A5hjdodHRw
50Oi8vb3BlbnNzbGNhLnRvYWQtY29uc3VsdGluZy5jb20vb3BlbnZwbi9MYXRlc3Qu
51Y3JsMBEGCWCGSAGG+EIBAQQEAwIGQDAxBglghkgBhvhCAQ0EJBYiVE9BRC1Db25z
52dWx0aW5nIHNlcnZlciBjZXJ0aWZpY2F0ZTANBgkqhkiG9w0BAQsFAAOCAgEAewDa
539BukGNJMex8gsXmmdaczTr8yh9Uvw4NJcZS38I+26o//2g+d6i7wxcQg8hIm62Hj
540TblGU3+RsJo4uzcWxxA5YUYlVszbHNBRpQengEE5pjwHvoXVMNES6Bt8xP04+Vj
550qVnA8gUaDMk9lN5anK7tF/mbHOIJwHJZYCa2t3y95dIOVEXFwOIzzbSbaprjkLN
56w0BgR5paJz7NZWNqo4sZHUUz94uH2bPEd01SqHO0dJwEVxadgxuPnD05I9gqGpGX
57Zf3Rn7EQylvUtX9mpPaulQPXc3emefewLUSSAdnZrVikZK2J/B4lSi9FpUwl4iQH
58pZoE0QLQHtB1SBKacnOAddGSTLSdFvpzjErjjWSpMukF0vutmrP86GG3xtshWVhI
59u+yLfDJVm/pXfaeDtWMXpxIT/U1i0avpk5MZtFMRC0MTaxEWBTnnJm+/yiaAXQYg
60E1ZIP0mkZkiUojIawTR7JTjHGhIraP9UVPNceVy0DLfETHEou3vhwBn7PFOz7piJ
61wjp3A47DStJD4fapaX6B1fqM+n34CMD9ZAiJFgQEIQfObAWC9hyr4m+pqkp1Qfuw
62vsAP/ZoS1CBirJfm3i+Gshh+VeH+TAmO/NBBYCfzBdgkNz4tJCkOc7CUT/NQTR/L
63N2OskR/Fkge149RJi7hHvE3gk/mtGtNmHJPuQ+s=
64-----END CERTIFICATE-----
65-----BEGIN CERTIFICATE-----
66MIIJazCCBVOgAwIBAgIUWHoc5e2FUECgyCvyVf8wCtt8gTYwDQYJKoZIhvcNAQEL
67BQAwRTELMAkGA1UEBhMCRlIxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
68GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMDA4MDQxODU4MTZaFw0yMDA5
69MDMxODU4MTZaMEUxCzAJBgNVBAYTAkZSMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw
70HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggQiMA0GCSqGSIb3DQEB
71AQUAA4IEDwAwggQKAoIEAQDARiuHkhrnf38Md1nxGDSneJfwv/QksdNNMNTJBdjg
72OVmaRCIAyz43oefTWDQ/TebbSwB+Lg9pud1zadGWhlZRhCgBPP8JDMhIKH4eXIRk
735IIa8WD08EwvSlqJL0r4gsMtVsxy7BZHAkka/2Ket9pyGt4kG5n75RFdc6BI80/8
74RwJt/MDxPrcVBAT7LnCluxQpyya9mZCabj7l+9a2yU2hgWS6QqfZJ133krkP/MMh
75AEQkSoA4mmBwWk9yPqXmUqiOi7v6iLkIUEh5SgYVPRk9BtU/kDaUdSwuqRrpCZo4
76SsWZWFLxBmLHkSh+G+BWjCVYMQr2ye7e+VMT/20+5xAfq4fj9n5BsPcx3QcVuTof
77RAc/Oygnt4MYnIcUb7zRFvCAvgpUHL7BnEn6nhyXjHJGqGDchsg8m9t3v/Y3ohq+
78qmrSzdeuylE1n3W5aWJlbFmyXegNP45MJ0xicesVrXEWF7YD/ir9mGJ8bQYr4blf
7977PrbF02komC6AzVPKOJa0jR+eW1wErzYlkYgez6ylBWCiHJd1dhEHlK3h2rXdYa
80Gnb45ILCLpEDjNEUrHifLLNXwqJpgZQsJU6BgMgk7ZgBfAKrCfTeg0rkCqCAPeVb
818eSLf7FBF7YBRJ5P6u8qXc4RtgEu607GaWV0gIMfyVBY52oV+OaNsEdFetrJnp3c
82friG8vJ+7jdq6zjUCGgnfUIHoViJPh3JuFfhA3jT0gQDKW5PeI7dxhrNvlqdYfHI
83fxX7Y1/J6cTQkqJ1cai2f0bwJIJiTAThNbG+zrtjJ7fZ3wJ4udyU/IKrwShqtmTb
841Ofj0tJDdwOH8i84vIySLUvR9aAb7ClFlnsx6rzwOxG90W7C0LA2M0EHm4FezJm/
85FfujnZwEWr1T9Wki6qE0MHCbdN/TTDws//EKkkE44FC+amL96w0IQl70vpE37j2A
86zlDWvFFID95SIxfmpkwWDvXDKv6gr1GMLeysCl2fgpY05Xidw5cEo9/tEkuWn/dG
87x/D9hnLBGeroA0251ES12jemqDjI2U0tfaeHakjwSsoWElf94Qmuh2iPZ+1zIxQs
887o6nAWN8X9hfsmrDTTHlww0TEfrjlbzG5Yh+0ZRxmejgiUyOCXck+eh/ZXMXvfWh
89y3CorIIuWgkRjm80PYkdaRDJdZuyP6R7tXfTXNVzAiSQf0Qx9ru2KB2Fs/XZPamH
90KjItAU5Q6msIVvaRMS0muQgV+b6hqSEBzqXqJfAlpVLHXr5FqK+U7EB9y02B6piB
91tAmxqXP8OOCoQql6/vgIcrDFUOo6KtGBW36ef74XE3KCUVaIzVJZSIt6i/Vi0bZj
92bAjsJUQ3qDlHdorv9TRVOhnC1GUz7SuYnpEOyiXmyx3LAgMBAAGjUzBRMB0GA1Ud
93DgQWBBQ62csZcH/meQcENHhNbqz9LMzwjjAfBgNVHSMEGDAWgBQ62csZcH/meQcE
94NHhNbqz9LMzwjjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IEAQBA
95wLsGf3R1+/I2zQE+lsj7RasZtA/Cos92iEGDAPvFbx9e+roG8Gg8KBsEJu/HN0JH
96lMMiQ8dDRHSBMvRBENL5/57oOOhmqc+1u5sazLuANhzAYPZG17Klib7YpEwWoXar
97FDDiJYtCyLW0oNLpCswYopWK9GC0RJNucB0NFvOxehJ2sP2/fxGBQMB09L6mjKjd
984KsOzyd3dNf0VYS6jB+/1pcKSHKQUo9HRHB5FK04PsYHoh4AtmEHvmYQKcWWidgU
99v26ftlH00ERzuW2juqBbz9mghlNRqXi0IyZ9b4tSj29dxW+WWFzo7j2zEPaD6z2W
100DEHq7zvON+g+q6qLgWeszqMgJzjvWjMj00E/t06PoHPiz/cAnDKEqp+ZzxCIFrxj
101/qneChpogDWyLbawhyyzbZvbirx5znOSbWjPZgydqaNEFViqbxwinBx4Xxabo6XN
102TU020FuMWmgfbIcvtgjKgyKqc97l7JMNNm7LQV9+9W0U5zdIqQKLZ9MMrd2w3xh4
103MAB8NKnwzHReK0TWwUU9HSgFAGdEX6HnyZ3bQ13ijg+sNBRMEi0gBHaqZKDdyoft
104B2u2uasSwioV48dbSIcHl+rTBKxiMh5XQ7ENnaGOJkjsIqTVzizqnPHU8eMBnSbb
105dsXlamROYII44+j3Ku6OGt51w86eGk4VxI3tmaECcJKqTkwUFD8AcNDrkjtmLuxK
10612yjnoM+u1cclfqQ5NOtRc6MJZ27jCobfBBhVdKVDp4X1WNyqGlbsU5adDAzknuI
107GT7MJO7lGjkZX2n54BNPSfrSknYMOVYcZqL0Dbcrhx5IyEmg+iOlOu1HO1tdnZop
108ej4vT+1V2w9Sa4Wo3UCo84jcm5v/4z7jCYh4BRQ60CFb7GLxZoqXIslcGSPool3n
109jl8JWoaLXrJUPfZGXo1iAlayJ5EiMyZl4eB/TBUf6TMm8vLvsPiUT+CEsjLppOdS
110eYppZAZ6H1JrJGs5kKBdOJHGn6Pkp5QsHIswOBd1HqHrBbYbZmDaDLRHduILWLrM
111e0/IfDdeXB/bKfmZoEpT8xRiauw15p0AHLumiK7KISAehfgBqUnxx+YmgGoZ7EWX
112KnMYAfCuC6oJ1DL0gp4Z9yMK1eu+GV1sLxPq9ZruEHW1R+H+4sGyiA5Gso2tgB6/
113XW//wxKclNp5LZR7hqfs/kGuh5asrJrnEbMwWn2+tr/LqfYtYh1D6nHfIXpT0o1d
114rNy/HrsKnRDMWxjm03r4hCViuNVD3Zb9anAF/NSPDVu8ATM5JbJNrCYX4eipz6ZE
115aQBkwIBkTPgtgP4r8v2G+uMYDw8nq7xh72FK107aeTTwc6MgU5jfeFNMr2XJisJd
116lSem1ngKYQSEzjVsTE4c
117-----END CERTIFICATE-----
diff --git a/scripts/announce-release b/scripts/announce-release
index 37e2ac4..c990821 100755
--- a/scripts/announce-release
+++ b/scripts/announce-release
@@ -210,20 +210,21 @@ else
210fi210fi
211211
212(echo "Please find the usual URLs below :"212(echo "Please find the usual URLs below :"
213 echo " Site index : http://www.haproxy.org/"213 echo " Site index : https://www.haproxy.org/"
214 echo " Documentation : http://docs.haproxy.org/"214 echo " Documentation : https://docs.haproxy.org/"
215 echo " Wiki : https://github.com/haproxy/wiki/wiki"215 echo " Wiki : https://github.com/haproxy/wiki/wiki"
216 echo " Discourse : http://discourse.haproxy.org/"216 echo " Discourse : https://discourse.haproxy.org/"
217 echo " Slack channel : https://slack.haproxy.org/"217 echo " Slack channel : https://slack.haproxy.org/"
218 echo " Issue tracker : https://github.com/haproxy/haproxy/issues"218 echo " Issue tracker : https://github.com/haproxy/haproxy/issues"
219 echo " Sources : http://www.haproxy.org/download/${BRANCH}/src/"219 echo " Sources : https://www.haproxy.org/download/${BRANCH}/src/"
220 echo " Git repository : http://git.haproxy.org/git/${gitdir}/"220 echo " Git repository : https://git.haproxy.org/git/${gitdir}/"
221 echo " Git Web browsing : http://git.haproxy.org/?p=${gitdir}"221 echo " Git Web browsing : https://git.haproxy.org/?p=${gitdir}"
222 echo " Changelog : http://www.haproxy.org/download/${BRANCH}/src/CHANGELOG"222 echo " Changelog : https://www.haproxy.org/download/${BRANCH}/src/CHANGELOG"
223 echo " Pending bugs : http://www.haproxy.org/l/pending-bugs"223 echo " Dataplane API : https://github.com/haproxytech/dataplaneapi/releases/latest"
224 echo " Reviewed bugs : http://www.haproxy.org/l/reviewed-bugs"224 echo " Pending bugs : https://www.haproxy.org/l/pending-bugs"
225 echo " Code reports : http://www.haproxy.org/l/code-reports"225 echo " Reviewed bugs : https://www.haproxy.org/l/reviewed-bugs"
226 echo " Latest builds : http://www.haproxy.org/l/dev-packages"226 echo " Code reports : https://www.haproxy.org/l/code-reports"
227 echo " Latest builds : https://www.haproxy.org/l/dev-packages"
227) >> "$OUTPUT"228) >> "$OUTPUT"
228229
229# sign230# sign
diff --git a/src/backend.c b/src/backend.c
index 6f2cc05..64780e4 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -2326,7 +2326,6 @@ void back_handle_st_cer(struct stream *s)
23262326
2327 /* only wait when we're retrying on the same server */2327 /* only wait when we're retrying on the same server */
2328 if ((si->state == SI_ST_ASS ||2328 if ((si->state == SI_ST_ASS ||
2329 (s->be->lbprm.algo & BE_LB_KIND) != BE_LB_KIND_RR ||
2330 (s->be->srv_act <= 1)) && !reused) {2329 (s->be->srv_act <= 1)) && !reused) {
2331 si->state = SI_ST_TAR;2330 si->state = SI_ST_TAR;
2332 si->exp = tick_add(now_ms, MS_TO_TICKS(delay));2331 si->exp = tick_add(now_ms, MS_TO_TICKS(delay));
diff --git a/src/cache.c b/src/cache.c
index ad4e715..ecf62fb 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -136,7 +136,7 @@ struct cache_st {
136struct cache_entry {136struct cache_entry {
137 unsigned int complete; /* An entry won't be valid until complete is not null. */137 unsigned int complete; /* An entry won't be valid until complete is not null. */
138 unsigned int latest_validation; /* latest validation date */138 unsigned int latest_validation; /* latest validation date */
139 unsigned int expire; /* expiration date */139 unsigned int expire; /* expiration date (wall clock time) */
140 unsigned int age; /* Origin server "Age" header value */140 unsigned int age; /* Origin server "Age" header value */
141141
142 struct eb32_node eb; /* ebtree node used to hold the cache object */142 struct eb32_node eb; /* ebtree node used to hold the cache object */
@@ -188,7 +188,7 @@ struct cache_entry *entry_exist(struct cache *cache, char *hash)
188 if (memcmp(entry->hash, hash, sizeof(entry->hash)))188 if (memcmp(entry->hash, hash, sizeof(entry->hash)))
189 return NULL;189 return NULL;
190190
191 if (entry->expire > now.tv_sec) {191 if (entry->expire > date.tv_sec) {
192 return entry;192 return entry;
193 } else {193 } else {
194 delete_entry(entry);194 delete_entry(entry);
@@ -249,7 +249,7 @@ struct cache_entry *secondary_entry_exist(struct cache *cache, struct cache_entr
249 * when we find them. Calling delete_entry would be too costly249 * when we find them. Calling delete_entry would be too costly
250 * so we simply call eb32_delete. The secondary_entry count will250 * so we simply call eb32_delete. The secondary_entry count will
251 * be updated when we try to insert a new entry to this list. */251 * be updated when we try to insert a new entry to this list. */
252 if (entry->expire <= now.tv_sec) {252 if (entry->expire <= date.tv_sec) {
253 eb32_delete(&entry->eb);253 eb32_delete(&entry->eb);
254 entry->eb.key = 0;254 entry->eb.key = 0;
255 }255 }
@@ -258,7 +258,7 @@ struct cache_entry *secondary_entry_exist(struct cache *cache, struct cache_entr
258 }258 }
259259
260 /* Expired entry */260 /* Expired entry */
261 if (entry && entry->expire <= now.tv_sec) {261 if (entry && entry->expire <= date.tv_sec) {
262 eb32_delete(&entry->eb);262 eb32_delete(&entry->eb);
263 entry->eb.key = 0;263 entry->eb.key = 0;
264 entry = NULL;264 entry = NULL;
@@ -283,7 +283,7 @@ static unsigned int clear_expired_duplicates(struct eb32_node **dup_tail)
283 while (prev) {283 while (prev) {
284 entry = container_of(prev, struct cache_entry, eb);284 entry = container_of(prev, struct cache_entry, eb);
285 prev = eb32_prev_dup(prev);285 prev = eb32_prev_dup(prev);
286 if (entry->expire <= now.tv_sec) {286 if (entry->expire <= date.tv_sec) {
287 eb32_delete(&entry->eb);287 eb32_delete(&entry->eb);
288 entry->eb.key = 0;288 entry->eb.key = 0;
289 }289 }
@@ -315,7 +315,7 @@ static struct eb32_node *insert_entry(struct cache *cache, struct cache_entry *n
315 struct eb32_node *prev = NULL;315 struct eb32_node *prev = NULL;
316 struct cache_entry *entry = NULL;316 struct cache_entry *entry = NULL;
317 unsigned int entry_count = 0;317 unsigned int entry_count = 0;
318 unsigned int last_clear_ts = now.tv_sec;318 unsigned int last_clear_ts = date.tv_sec;
319319
320 struct eb32_node *node = eb32_insert(&cache->entries, &new_entry->eb);320 struct eb32_node *node = eb32_insert(&cache->entries, &new_entry->eb);
321321
@@ -338,7 +338,7 @@ static struct eb32_node *insert_entry(struct cache *cache, struct cache_entry *n
338 * space. In order to avoid going over the same list too338 * space. In order to avoid going over the same list too
339 * often, we first check the timestamp of the last check339 * often, we first check the timestamp of the last check
340 * performed. */340 * performed. */
341 if (last_clear_ts == now.tv_sec) {341 if (last_clear_ts == date.tv_sec) {
342 /* Too many entries for this primary key, clear the342 /* Too many entries for this primary key, clear the
343 * one that was inserted. */343 * one that was inserted. */
344 eb32_delete(node);344 eb32_delete(node);
@@ -351,7 +351,7 @@ static struct eb32_node *insert_entry(struct cache *cache, struct cache_entry *n
351 /* Still too many entries for this primary key, delete351 /* Still too many entries for this primary key, delete
352 * the newly inserted one. */352 * the newly inserted one. */
353 entry = container_of(prev, struct cache_entry, eb);353 entry = container_of(prev, struct cache_entry, eb);
354 entry->last_clear_ts = now.tv_sec;354 entry->last_clear_ts = date.tv_sec;
355 eb32_delete(node);355 eb32_delete(node);
356 node->key = 0;356 node->key = 0;
357 return NULL;357 return NULL;
@@ -811,8 +811,8 @@ int http_calc_maxage(struct stream *s, struct cache *cache, int *true_maxage)
811 /* A request having an expiring date earlier811 /* A request having an expiring date earlier
812 * than the current date should be considered as812 * than the current date should be considered as
813 * stale. */813 * stale. */
814 expires = (expires_val >= now.tv_sec) ?814 expires = (expires_val >= date.tv_sec) ?
815 (expires_val - now.tv_sec) : 0;815 (expires_val - date.tv_sec) : 0;
816 }816 }
817 else {817 else {
818 /* Following RFC 7234#5.3, an invalid date818 /* Following RFC 7234#5.3, an invalid date
@@ -886,7 +886,7 @@ static time_t get_last_modified_time(struct htx *htx)
886 /* Fallback on the current time if no "Last-Modified" or "Date" header886 /* Fallback on the current time if no "Last-Modified" or "Date" header
887 * was found. */887 * was found. */
888 if (!last_modified)888 if (!last_modified)
889 last_modified = now.tv_sec;889 last_modified = date.tv_sec;
890890
891 return last_modified;891 return last_modified;
892}892}
@@ -1120,7 +1120,7 @@ enum act_return http_action_store_cache(struct act_rule *rule, struct proxy *px,
1120 * is set by the end of this function (in case of concurrent accesses to1120 * is set by the end of this function (in case of concurrent accesses to
1121 * the same resource). This way the second access will find an existing1121 * the same resource). This way the second access will find an existing
1122 * but not yet usable entry in the tree and will avoid storing its data. */1122 * but not yet usable entry in the tree and will avoid storing its data. */
1123 object->expire = now.tv_sec + 2;1123 object->expire = date.tv_sec + 2;
11241124
1125 memcpy(object->hash, txn->cache_hash, sizeof(object->hash));1125 memcpy(object->hash, txn->cache_hash, sizeof(object->hash));
1126 if (vary_signature)1126 if (vary_signature)
@@ -1224,8 +1224,8 @@ enum act_return http_action_store_cache(struct act_rule *rule, struct proxy *px,
1224 if (cache_ctx) {1224 if (cache_ctx) {
1225 cache_ctx->first_block = first;1225 cache_ctx->first_block = first;
1226 /* store latest value and expiration time */1226 /* store latest value and expiration time */
1227 object->latest_validation = now.tv_sec;1227 object->latest_validation = date.tv_sec;
1228 object->expire = now.tv_sec + effective_maxage;1228 object->expire = date.tv_sec + effective_maxage;
1229 return ACT_RET_CONT;1229 return ACT_RET_CONT;
1230 }1230 }
12311231
@@ -1416,7 +1416,7 @@ static int htx_cache_add_age_hdr(struct appctx *appctx, struct htx *htx)
1416 char *end;1416 char *end;
14171417
1418 chunk_reset(&trash);1418 chunk_reset(&trash);
1419 age = MAX(0, (int)(now.tv_sec - cache_ptr->latest_validation)) + cache_ptr->age;1419 age = MAX(0, (int)(date.tv_sec - cache_ptr->latest_validation)) + cache_ptr->age;
1420 if (unlikely(age > CACHE_ENTRY_MAX_AGE))1420 if (unlikely(age > CACHE_ENTRY_MAX_AGE))
1421 age = CACHE_ENTRY_MAX_AGE;1421 age = CACHE_ENTRY_MAX_AGE;
1422 end = ultoa_o(age, b_head(&trash), b_size(&trash));1422 end = ultoa_o(age, b_head(&trash), b_size(&trash));
@@ -2602,13 +2602,13 @@ static int cli_io_handler_show_cache(struct appctx *appctx)
2602 entry = container_of(node, struct cache_entry, eb);2602 entry = container_of(node, struct cache_entry, eb);
2603 next_key = node->key + 1;2603 next_key = node->key + 1;
26042604
2605 if (entry->expire > now.tv_sec) {2605 if (entry->expire > date.tv_sec) {
2606 chunk_printf(&trash, "%p hash:%u vary:0x", entry, read_u32(entry->hash));2606 chunk_printf(&trash, "%p hash:%u vary:0x", entry, read_u32(entry->hash));
2607 for (i = 0; i < HTTP_CACHE_SEC_KEY_LEN; ++i)2607 for (i = 0; i < HTTP_CACHE_SEC_KEY_LEN; ++i)
2608 chunk_appendf(&trash, "%02x", (unsigned char)entry->secondary_key[i]);2608 chunk_appendf(&trash, "%02x", (unsigned char)entry->secondary_key[i]);
2609 chunk_appendf(&trash, " size:%u (%u blocks), refcount:%u, expire:%d\n",2609 chunk_appendf(&trash, " size:%u (%u blocks), refcount:%u, expire:%d\n",
2610 block_ptr(entry)->len, block_ptr(entry)->block_count,2610 block_ptr(entry)->len, block_ptr(entry)->block_count,
2611 block_ptr(entry)->refcount, entry->expire - (int)now.tv_sec);2611 block_ptr(entry)->refcount, entry->expire - (int)date.tv_sec);
2612 } else {2612 } else {
2613 /* time to remove that one */2613 /* time to remove that one */
2614 delete_entry(entry);2614 delete_entry(entry);
diff --git a/src/cfgparse-listen.c b/src/cfgparse-listen.c
index 4603376..35bd498 100644
--- a/src/cfgparse-listen.c
+++ b/src/cfgparse-listen.c
@@ -292,6 +292,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
292 curr_defproxy = last_defproxy;292 curr_defproxy = last_defproxy;
293293
294 if (strcmp(args[arg], "from") == 0) {294 if (strcmp(args[arg], "from") == 0) {
295 struct ebpt_node *next_by_name;
296
295 curr_defproxy = proxy_find_by_name(args[arg+1], PR_CAP_DEF, 0);297 curr_defproxy = proxy_find_by_name(args[arg+1], PR_CAP_DEF, 0);
296298
297 if (!curr_defproxy) {299 if (!curr_defproxy) {
@@ -300,8 +302,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
300 goto out;302 goto out;
301 }303 }
302304
303 if (ebpt_next_dup(&curr_defproxy->conf.by_name)) {305 if ((next_by_name = ebpt_next_dup(&curr_defproxy->conf.by_name))) {
304 struct proxy *px2 = container_of(ebpt_next_dup(&curr_defproxy->conf.by_name), struct proxy, conf.by_name);306 struct proxy *px2 = container_of(next_by_name, struct proxy, conf.by_name);
305307
306 ha_alert("parsing [%s:%d] : ambiguous defaults section name '%s' referenced by %s '%s' exists at least at %s:%d and %s:%d.\n",308 ha_alert("parsing [%s:%d] : ambiguous defaults section name '%s' referenced by %s '%s' exists at least at %s:%d and %s:%d.\n",
307 file, linenum, args[arg+1], proxy_cap_str(rc), name,309 file, linenum, args[arg+1], proxy_cap_str(rc), name,
diff --git a/src/cfgparse-ssl.c b/src/cfgparse-ssl.c
index 654b020..fcd0416 100644
--- a/src/cfgparse-ssl.c
+++ b/src/cfgparse-ssl.c
@@ -758,7 +758,7 @@ static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, str
758{758{
759 int code;759 int code;
760 char *p = args[cur_arg + 1];760 char *p = args[cur_arg + 1];
761 unsigned long long *ignerr = &conf->crt_ignerr;761 unsigned long long *ignerr = conf->crt_ignerr_bitfield;
762762
763 if (!*p) {763 if (!*p) {
764 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);764 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
@@ -766,21 +766,21 @@ static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, str
766 }766 }
767767
768 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)768 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
769 ignerr = &conf->ca_ignerr;769 ignerr = conf->ca_ignerr_bitfield;
770770
771 if (strcmp(p, "all") == 0) {771 if (strcmp(p, "all") == 0) {
772 *ignerr = ~0ULL;772 cert_ignerr_bitfield_set_all(ignerr);
773 return 0;773 return 0;
774 }774 }
775775
776 while (p) {776 while (p) {
777 code = atoi(p);777 code = atoi(p);
778 if ((code <= 0) || (code > 63)) {778 if ((code <= 0) || (code > SSL_MAX_VFY_ERROR_CODE)) {
779 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",779 memprintf(err, "'%s' : ID '%d' out of range (1..%d) in error IDs list '%s'",
780 args[cur_arg], code, args[cur_arg + 1]);780 args[cur_arg], code, SSL_MAX_VFY_ERROR_CODE, args[cur_arg + 1]);
781 return ERR_ALERT | ERR_FATAL;781 return ERR_ALERT | ERR_FATAL;
782 }782 }
783 *ignerr |= 1ULL << code;783 cert_ignerr_bitfield_set(ignerr, code);
784 p = strchr(p, ',');784 p = strchr(p, ',');
785 if (p)785 if (p)
786 p++;786 p++;
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 4b42ec0..27bab1d 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -10,10 +10,10 @@
10 *10 *
11 */11 */
1212
13#ifdef USE_LIBCRYPT13/* This is to have crypt() and sched_setaffinity() defined on Linux */
14/* This is to have crypt() defined on Linux */
15#define _GNU_SOURCE14#define _GNU_SOURCE
1615
16#ifdef USE_LIBCRYPT
17#ifdef USE_CRYPT_H17#ifdef USE_CRYPT_H
18/* some platforms such as Solaris need this */18/* some platforms such as Solaris need this */
19#include <crypt.h>19#include <crypt.h>
@@ -29,6 +29,9 @@
29#include <pwd.h>29#include <pwd.h>
30#include <grp.h>30#include <grp.h>
31#include <errno.h>31#include <errno.h>
32#ifdef USE_CPU_AFFINITY
33#include <sched.h>
34#endif
32#include <sys/types.h>35#include <sys/types.h>
33#include <sys/stat.h>36#include <sys/stat.h>
34#include <fcntl.h>37#include <fcntl.h>
@@ -62,6 +65,7 @@
62#include <haproxy/lb_map.h>65#include <haproxy/lb_map.h>
63#include <haproxy/listener.h>66#include <haproxy/listener.h>
64#include <haproxy/log.h>67#include <haproxy/log.h>
68#include <haproxy/sink.h>
65#include <haproxy/mailers.h>69#include <haproxy/mailers.h>
66#include <haproxy/namespace.h>70#include <haproxy/namespace.h>
67#include <haproxy/obj_type-t.h>71#include <haproxy/obj_type-t.h>
@@ -2630,6 +2634,7 @@ int check_config_validity()
2630{2634{
2631 int cfgerr = 0;2635 int cfgerr = 0;
2632 struct proxy *curproxy = NULL;2636 struct proxy *curproxy = NULL;
2637 struct proxy *init_proxies_list = NULL;
2633 struct stktable *t;2638 struct stktable *t;
2634 struct server *newsrv = NULL;2639 struct server *newsrv = NULL;
2635 int err_code = 0;2640 int err_code = 0;
@@ -2707,7 +2712,11 @@ int check_config_validity()
2707 proxies_list = next;2712 proxies_list = next;
2708 }2713 }
27092714
2710 for (curproxy = proxies_list; curproxy; curproxy = curproxy->next) {2715 /* starting to initialize the main proxies list */
2716 init_proxies_list = proxies_list;
2717
2718init_proxies_list_stage1:
2719 for (curproxy = init_proxies_list; curproxy; curproxy = curproxy->next) {
2711 struct switching_rule *rule;2720 struct switching_rule *rule;
2712 struct server_rule *srule;2721 struct server_rule *srule;
2713 struct sticking_rule *mrule;2722 struct sticking_rule *mrule;
@@ -2837,11 +2846,16 @@ int check_config_validity()
2837 case PR_MODE_CLI:2846 case PR_MODE_CLI:
2838 cfgerr += proxy_cfg_ensure_no_http(curproxy);2847 cfgerr += proxy_cfg_ensure_no_http(curproxy);
2839 break;2848 break;
2849
2840 case PR_MODE_SYSLOG:2850 case PR_MODE_SYSLOG:
2851 /* this mode is initialized as the classic tcp proxy */
2852 cfgerr += proxy_cfg_ensure_no_http(curproxy);
2853 break;
2854
2841 case PR_MODE_PEERS:2855 case PR_MODE_PEERS:
2842 case PR_MODES:2856 case PR_MODES:
2843 /* should not happen, bug gcc warn missing switch statement */2857 /* should not happen, bug gcc warn missing switch statement */
2844 ha_alert("config : %s '%s' cannot use peers or syslog mode for this proxy. NOTE: PLEASE REPORT THIS TO DEVELOPERS AS YOU'RE NOT SUPPOSED TO BE ABLE TO CREATE A CONFIGURATION TRIGGERING THIS!\n",2858 ha_alert("config: %s '%s' cannot initialize this proxy mode (peers) in this way. NOTE: PLEASE REPORT THIS TO DEVELOPERS AS YOU'RE NOT SUPPOSED TO BE ABLE TO CREATE A CONFIGURATION TRIGGERING THIS!\n",
2845 proxy_type_str(curproxy), curproxy->id);2859 proxy_type_str(curproxy), curproxy->id);
2846 cfgerr++;2860 cfgerr++;
2847 break;2861 break;
@@ -3966,6 +3980,24 @@ out_uri_auth_compat:
3966 }3980 }
3967 }3981 }
39683982
3983 /*
3984 * We have just initialized the main proxies list
3985 * we must also configure the log-forward proxies list
3986 */
3987 if (init_proxies_list == proxies_list) {
3988 init_proxies_list = cfg_log_forward;
3989 /* check if list is not null to avoid infinite loop */
3990 if (init_proxies_list)
3991 goto init_proxies_list_stage1;
3992 }
3993
3994 if (init_proxies_list == cfg_log_forward) {
3995 init_proxies_list = sink_proxies_list;
3996 /* check if list is not null to avoid infinite loop */
3997 if (init_proxies_list)
3998 goto init_proxies_list_stage1;
3999 }
4000
3969 /***********************************************************/4001 /***********************************************************/
3970 /* At this point, target names have already been resolved. */4002 /* At this point, target names have already been resolved. */
3971 /***********************************************************/4003 /***********************************************************/
@@ -4087,7 +4119,11 @@ out_uri_auth_compat:
40874119
4088 /* perform the final checks before creating tasks */4120 /* perform the final checks before creating tasks */
40894121
4090 for (curproxy = proxies_list; curproxy; curproxy = curproxy->next) {4122 /* starting to initialize the main proxies list */
4123 init_proxies_list = proxies_list;
4124
4125init_proxies_list_stage2:
4126 for (curproxy = init_proxies_list; curproxy; curproxy = curproxy->next) {
4091 struct listener *listener;4127 struct listener *listener;
4092 unsigned int next_id;4128 unsigned int next_id;
40934129
@@ -4209,6 +4245,17 @@ out_uri_auth_compat:
4209 }4245 }
42104246
4211 /*4247 /*
4248 * We have just initialized the main proxies list
4249 * we must also configure the log-forward proxies list
4250 */
4251 if (init_proxies_list == proxies_list) {
4252 init_proxies_list = cfg_log_forward;
4253 /* check if list is not null to avoid infinite loop */
4254 if (init_proxies_list)
4255 goto init_proxies_list_stage2;
4256 }
4257
4258 /*
4212 * Recount currently required checks.4259 * Recount currently required checks.
4213 */4260 */
42144261
diff --git a/src/check.c b/src/check.c
index 1a40b6f..2205063 100644
--- a/src/check.c
+++ b/src/check.c
@@ -1715,6 +1715,13 @@ static int init_srv_agent_check(struct server *srv)
1715 LIST_INSERT(srv->agent.tcpcheck_rules->list, &chk->list);1715 LIST_INSERT(srv->agent.tcpcheck_rules->list, &chk->list);
1716 }1716 }
17171717
1718 /* <chk> is always defined here and it is a CONNECT action. If there is
1719 * a preset variable, it means there is an agent string defined and data
1720 * will be sent after the connect.
1721 */
1722 if (!LIST_ISEMPTY(&srv->agent.tcpcheck_rules->preset_vars))
1723 chk->connect.options |= TCPCHK_OPT_HAS_DATA;
1724
17181725
1719 err = init_check(&srv->agent, PR_O2_TCPCHK_CHK);1726 err = init_check(&srv->agent, PR_O2_TCPCHK_CHK);
1720 if (err) {1727 if (err) {
diff --git a/src/dns.c b/src/dns.c
index 1ef5e87..c4b2af0 100644
--- a/src/dns.c
+++ b/src/dns.c
@@ -1023,7 +1023,7 @@ struct dns_session *dns_session_new(struct dns_stream_server *dss)
1023 if (dss->maxconn && (dss->maxconn <= dss->cur_conns))1023 if (dss->maxconn && (dss->maxconn <= dss->cur_conns))
1024 return NULL;1024 return NULL;
10251025
1026 ds = pool_alloc(dns_session_pool);1026 ds = pool_zalloc(dns_session_pool);
1027 if (!ds)1027 if (!ds)
1028 return NULL;1028 return NULL;
10291029
diff --git a/src/ev_epoll.c b/src/ev_epoll.c
index 330c38c..041d6d8 100644
--- a/src/ev_epoll.c
+++ b/src/ev_epoll.c
@@ -185,7 +185,7 @@ static void _do_poll(struct poller *p, int exp, int wake)
185185
186 thread_harmless_now();186 thread_harmless_now();
187187
188 /* now let's wait for polled events */188 /* Now let's wait for polled events. */
189 wait_time = wake ? 0 : compute_poll_timeout(exp);189 wait_time = wake ? 0 : compute_poll_timeout(exp);
190 tv_entering_poll();190 tv_entering_poll();
191 activity_count_runtime();191 activity_count_runtime();
@@ -201,7 +201,7 @@ static void _do_poll(struct poller *p, int exp, int wake)
201 }201 }
202 if (timeout || !wait_time)202 if (timeout || !wait_time)
203 break;203 break;
204 if (signal_queue_len || wake)204 if (wake)
205 break;205 break;
206 if (tick_isset(exp) && tick_is_expired(exp, now_ms))206 if (tick_isset(exp) && tick_is_expired(exp, now_ms))
207 break;207 break;
diff --git a/src/ev_evports.c b/src/ev_evports.c
index 109e59c..e012e00 100644
--- a/src/ev_evports.c
+++ b/src/ev_evports.c
@@ -153,9 +153,7 @@ static void _do_poll(struct poller *p, int exp, int wake)
153153
154 thread_harmless_now();154 thread_harmless_now();
155155
156 /*156 /* Now let's wait for polled events. */
157 * Determine how long to wait for events to materialise on the port.
158 */
159 wait_time = wake ? 0 : compute_poll_timeout(exp);157 wait_time = wake ? 0 : compute_poll_timeout(exp);
160 tv_entering_poll();158 tv_entering_poll();
161 activity_count_runtime();159 activity_count_runtime();
@@ -195,7 +193,7 @@ static void _do_poll(struct poller *p, int exp, int wake)
195 break;193 break;
196 if (timeout || !wait_time)194 if (timeout || !wait_time)
197 break;195 break;
198 if (signal_queue_len || wake)196 if (wake)
199 break;197 break;
200 if (tick_isset(exp) && tick_is_expired(exp, now_ms))198 if (tick_isset(exp) && tick_is_expired(exp, now_ms))
201 break;199 break;
diff --git a/src/ev_kqueue.c b/src/ev_kqueue.c
index d51a833..0d81d67 100644
--- a/src/ev_kqueue.c
+++ b/src/ev_kqueue.c
@@ -141,7 +141,7 @@ static void _do_poll(struct poller *p, int exp, int wake)
141 }141 }
142 fd_nbupdt = 0;142 fd_nbupdt = 0;
143143
144 /* now let's wait for events */144 /* Now let's wait for polled events. */
145 wait_time = wake ? 0 : compute_poll_timeout(exp);145 wait_time = wake ? 0 : compute_poll_timeout(exp);
146 fd = global.tune.maxpollevents;146 fd = global.tune.maxpollevents;
147 tv_entering_poll();147 tv_entering_poll();
@@ -167,7 +167,7 @@ static void _do_poll(struct poller *p, int exp, int wake)
167 }167 }
168 if (timeout || !wait_time)168 if (timeout || !wait_time)
169 break;169 break;
170 if (signal_queue_len || wake)170 if (wake)
171 break;171 break;
172 if (tick_isset(exp) && tick_is_expired(exp, now_ms))172 if (tick_isset(exp) && tick_is_expired(exp, now_ms))
173 break;173 break;
diff --git a/src/ev_poll.c b/src/ev_poll.c
index c30aadb..4d136a0 100644
--- a/src/ev_poll.c
+++ b/src/ev_poll.c
@@ -21,6 +21,7 @@
21#include <haproxy/api.h>21#include <haproxy/api.h>
22#include <haproxy/fd.h>22#include <haproxy/fd.h>
23#include <haproxy/global.h>23#include <haproxy/global.h>
24#include <haproxy/signal.h>
24#include <haproxy/ticks.h>25#include <haproxy/ticks.h>
25#include <haproxy/time.h>26#include <haproxy/time.h>
2627
@@ -198,7 +199,7 @@ static void _do_poll(struct poller *p, int exp, int wake)
198 }199 }
199 }200 }
200201
201 /* now let's wait for events */202 /* Now let's wait for polled events. */
202 wait_time = wake ? 0 : compute_poll_timeout(exp);203 wait_time = wake ? 0 : compute_poll_timeout(exp);
203 tv_entering_poll();204 tv_entering_poll();
204 activity_count_runtime();205 activity_count_runtime();
diff --git a/src/fcgi-app.c b/src/fcgi-app.c
index 29a3602..8fca1e9 100644
--- a/src/fcgi-app.c
+++ b/src/fcgi-app.c
@@ -589,7 +589,7 @@ static int proxy_parse_use_fcgi_app(char **args, int section, struct proxy *curp
589 struct fcgi_flt_conf *fcgi_conf = NULL;589 struct fcgi_flt_conf *fcgi_conf = NULL;
590 int retval = 0;590 int retval = 0;
591591
592 if (!(curpx->cap & PR_CAP_BE)) {592 if ((curpx->cap & PR_CAP_DEF) || !(curpx->cap & PR_CAP_BE)) {
593 memprintf(err, "'%s' only available in backend or listen section", args[0]);593 memprintf(err, "'%s' only available in backend or listen section", args[0]);
594 retval = -1;594 retval = -1;
595 goto end;595 goto end;
diff --git a/src/fcgi.c b/src/fcgi.c
index 1c2543d..778ce9e 100644
--- a/src/fcgi.c
+++ b/src/fcgi.c
@@ -47,7 +47,7 @@ int fcgi_encode_record_hdr(struct buffer *out, const struct fcgi_header *h)
47 out->area[len++] = ((h->len >> 8) & 0xff);47 out->area[len++] = ((h->len >> 8) & 0xff);
48 out->area[len++] = (h->len & 0xff);48 out->area[len++] = (h->len & 0xff);
49 out->area[len++] = h->padding;49 out->area[len++] = h->padding;
50 len++; /* rsv */50 out->area[len++] = 0; /* rsv */
5151
52 out->data = len;52 out->data = len;
53 return 1;53 return 1;
@@ -94,7 +94,11 @@ int fcgi_encode_begin_request(struct buffer *out, const struct fcgi_begin_reques
94 out->area[len++] = ((r->role >> 8) & 0xff);94 out->area[len++] = ((r->role >> 8) & 0xff);
95 out->area[len++] = (r->role & 0xff);95 out->area[len++] = (r->role & 0xff);
96 out->area[len++] = r->flags;96 out->area[len++] = r->flags;
97 len += 5; /* rsv */97 out->area[len++] = 0; /* rsv */
98 out->area[len++] = 0;
99 out->area[len++] = 0;
100 out->area[len++] = 0;
101 out->area[len++] = 0;
98102
99 out->data = len;103 out->data = len;
100 return 1;104 return 1;
diff --git a/src/fd.c b/src/fd.c
index b9c8ccc..3c9629f 100644
--- a/src/fd.c
+++ b/src/fd.c
@@ -206,7 +206,7 @@ lock_self:
206#ifdef HA_CAS_IS_8B206#ifdef HA_CAS_IS_8B
207 unlikely(!_HA_ATOMIC_CAS(((uint64_t *)&_GET_NEXT(fd, off)), (uint64_t *)&cur_list.u64, next_list.u64))207 unlikely(!_HA_ATOMIC_CAS(((uint64_t *)&_GET_NEXT(fd, off)), (uint64_t *)&cur_list.u64, next_list.u64))
208#else208#else
209 unlikely(!_HA_ATOMIC_DWCAS(((long *)&_GET_NEXT(fd, off)), (uint32_t *)&cur_list.u32, &next_list.u32))209 unlikely(!_HA_ATOMIC_DWCAS(((long *)&_GET_NEXT(fd, off)), (uint32_t *)&cur_list.u32, (const uint32_t *)&next_list.u32))
210#endif210#endif
211 );211 );
212 next = cur_list.ent.next;212 next = cur_list.ent.next;
@@ -666,9 +666,9 @@ static void deinit_pollers_per_thread()
666 /* rd and wr are init at the same place, but only rd is init to -1, so666 /* rd and wr are init at the same place, but only rd is init to -1, so
667 we rely to rd to close. */667 we rely to rd to close. */
668 if (poller_rd_pipe > -1) {668 if (poller_rd_pipe > -1) {
669 close(poller_rd_pipe);669 fd_delete(poller_rd_pipe);
670 poller_rd_pipe = -1;670 poller_rd_pipe = -1;
671 close(poller_wr_pipe[tid]);671 fd_delete(poller_wr_pipe[tid]);
672 poller_wr_pipe[tid] = -1;672 poller_wr_pipe[tid] = -1;
673 }673 }
674}674}
diff --git a/src/flt_http_comp.c b/src/flt_http_comp.c
index a9c49f5..66eb601 100644
--- a/src/flt_http_comp.c
+++ b/src/flt_http_comp.c
@@ -304,23 +304,18 @@ set_compression_response_header(struct comp_state *st, struct stream *s, struct
304 struct htx_sl *sl;304 struct htx_sl *sl;
305 struct http_hdr_ctx ctx;305 struct http_hdr_ctx ctx;
306306
307 /*
308 * Add Content-Encoding header when it's not identity encoding.
309 * RFC 2616 : Identity encoding: This content-coding is used only in the
310 * Accept-Encoding header, and SHOULD NOT be used in the Content-Encoding
311 * header.
312 */
313 if (st->comp_algo->cfg_name_len != 8 || memcmp(st->comp_algo->cfg_name, "identity", 8) != 0) {
314 struct ist v = ist2(st->comp_algo->ua_name, st->comp_algo->ua_name_len);
315
316 if (!http_add_header(htx, ist("Content-Encoding"), v))
317 goto error;
318 }
319
320 sl = http_get_stline(htx);307 sl = http_get_stline(htx);
321 if (!sl)308 if (!sl)
322 goto error;309 goto error;
323310
311 /* add "Transfer-Encoding: chunked" header */
312 if (!(msg->flags & HTTP_MSGF_TE_CHNK)) {
313 if (!http_add_header(htx, ist("Transfer-Encoding"), ist("chunked")))
314 goto error;
315 msg->flags |= HTTP_MSGF_TE_CHNK;
316 sl->flags |= (HTX_SL_F_XFER_ENC|HTX_SL_F_CHNK);
317 }
318
324 /* remove Content-Length header */319 /* remove Content-Length header */
325 if (msg->flags & HTTP_MSGF_CNT_LEN) {320 if (msg->flags & HTTP_MSGF_CNT_LEN) {
326 ctx.blk = NULL;321 ctx.blk = NULL;
@@ -330,14 +325,6 @@ set_compression_response_header(struct comp_state *st, struct stream *s, struct
330 sl->flags &= ~HTX_SL_F_CLEN;325 sl->flags &= ~HTX_SL_F_CLEN;
331 }326 }
332327
333 /* add "Transfer-Encoding: chunked" header */
334 if (!(msg->flags & HTTP_MSGF_TE_CHNK)) {
335 if (!http_add_header(htx, ist("Transfer-Encoding"), ist("chunked")))
336 goto error;
337 msg->flags |= HTTP_MSGF_TE_CHNK;
338 sl->flags |= (HTX_SL_F_XFER_ENC|HTX_SL_F_CHNK);
339 }
340
341 /* convert "ETag" header to a weak ETag */328 /* convert "ETag" header to a weak ETag */
342 ctx.blk = NULL;329 ctx.blk = NULL;
343 if (http_find_header(htx, ist("ETag"), &ctx, 1)) {330 if (http_find_header(htx, ist("ETag"), &ctx, 1)) {
@@ -355,6 +342,19 @@ set_compression_response_header(struct comp_state *st, struct stream *s, struct
355 if (!http_add_header(htx, ist("Vary"), ist("Accept-Encoding")))342 if (!http_add_header(htx, ist("Vary"), ist("Accept-Encoding")))
356 goto error;343 goto error;
357344
345 /*
346 * Add Content-Encoding header when it's not identity encoding.
347 * RFC 2616 : Identity encoding: This content-coding is used only in the
348 * Accept-Encoding header, and SHOULD NOT be used in the Content-Encoding
349 * header.
350 */
351 if (st->comp_algo->cfg_name_len != 8 || memcmp(st->comp_algo->cfg_name, "identity", 8) != 0) {
352 struct ist v = ist2(st->comp_algo->ua_name, st->comp_algo->ua_name_len);
353
354 if (!http_add_header(htx, ist("Content-Encoding"), v))
355 goto error;
356 }
357
358 return 1;358 return 1;
359359
360 error:360 error:
diff --git a/src/flt_spoe.c b/src/flt_spoe.c
index cb7eed4..4826aa0 100644
--- a/src/flt_spoe.c
+++ b/src/flt_spoe.c
@@ -1259,7 +1259,7 @@ spoe_release_appctx(struct appctx *appctx)
1259 /* Destroy the task attached to this applet */1259 /* Destroy the task attached to this applet */
1260 task_destroy(spoe_appctx->task);1260 task_destroy(spoe_appctx->task);
12611261
1262 /* Notify all waiting streams */1262 /* Report an error to all streams in the appctx waiting queue */
1263 list_for_each_entry_safe(ctx, back, &spoe_appctx->waiting_queue, list) {1263 list_for_each_entry_safe(ctx, back, &spoe_appctx->waiting_queue, list) {
1264 LIST_DELETE(&ctx->list);1264 LIST_DELETE(&ctx->list);
1265 LIST_INIT(&ctx->list);1265 LIST_INIT(&ctx->list);
@@ -1271,8 +1271,8 @@ spoe_release_appctx(struct appctx *appctx)
1271 task_wakeup(ctx->strm->task, TASK_WOKEN_MSG);1271 task_wakeup(ctx->strm->task, TASK_WOKEN_MSG);
1272 }1272 }
12731273
1274 /* If the applet was processing a fragmented frame, notify the1274 /* If the applet was processing a fragmented frame, report an error to
1275 * corresponding stream. */1275 * the corresponding stream. */
1276 if (spoe_appctx->frag_ctx.ctx) {1276 if (spoe_appctx->frag_ctx.ctx) {
1277 ctx = spoe_appctx->frag_ctx.ctx;1277 ctx = spoe_appctx->frag_ctx.ctx;
1278 ctx->spoe_appctx = NULL;1278 ctx->spoe_appctx = NULL;
@@ -1281,7 +1281,11 @@ spoe_release_appctx(struct appctx *appctx)
1281 task_wakeup(ctx->strm->task, TASK_WOKEN_MSG);1281 task_wakeup(ctx->strm->task, TASK_WOKEN_MSG);
1282 }1282 }
12831283
1284 if (!LIST_ISEMPTY(&agent->rt[tid].waiting_queue)) {1284 if (!LIST_ISEMPTY(&agent->rt[tid].applets)) {
1285 /* If there are still some running applets, remove reference on
1286 * the current one from streams in the async waiting queue. In
1287 * async mode, the ACK may be received from another appctx.
1288 */
1285 list_for_each_entry_safe(ctx, back, &agent->rt[tid].waiting_queue, list) {1289 list_for_each_entry_safe(ctx, back, &agent->rt[tid].waiting_queue, list) {
1286 if (ctx->spoe_appctx == spoe_appctx)1290 if (ctx->spoe_appctx == spoe_appctx)
1287 ctx->spoe_appctx = NULL;1291 ctx->spoe_appctx = NULL;
@@ -1289,16 +1293,25 @@ spoe_release_appctx(struct appctx *appctx)
1289 goto end;1293 goto end;
1290 }1294 }
1291 else {1295 else {
1292 /* It is the last running applet and the sending and waiting1296 /* It is the last running applet and the sending and async
1293 * queues are not empty. Try to start a new one if HAproxy is1297 * waiting queues are not empty. So try to start a new applet if
1294 * not stopping.1298 * HAproxy is not stopping. On success, we remove reference on
1299 * the current appctx from streams in the async waiting queue.
1300 * In async mode, the ACK may be received from another appctx.
1295 */1301 */
1296 if (!stopping &&1302 if (!stopping &&
1297 (!LIST_ISEMPTY(&agent->rt[tid].sending_queue) || !LIST_ISEMPTY(&agent->rt[tid].waiting_queue)) &&1303 (!LIST_ISEMPTY(&agent->rt[tid].sending_queue) || !LIST_ISEMPTY(&agent->rt[tid].waiting_queue)) &&
1298 spoe_create_appctx(agent->spoe_conf))1304 spoe_create_appctx(agent->spoe_conf)) {
1305 list_for_each_entry_safe(ctx, back, &agent->rt[tid].waiting_queue, list) {
1306 if (ctx->spoe_appctx == spoe_appctx)
1307 ctx->spoe_appctx = NULL;
1308 }
1299 goto end;1309 goto end;
1310 }
13001311
1301 /* otherwise, notify all waiting streams */1312 /* Otherwise, report an error to all streams in the sending and
1313 * async waiting queues.
1314 */
1302 list_for_each_entry_safe(ctx, back, &agent->rt[tid].sending_queue, list) {1315 list_for_each_entry_safe(ctx, back, &agent->rt[tid].sending_queue, list) {
1303 LIST_DELETE(&ctx->list);1316 LIST_DELETE(&ctx->list);
1304 LIST_INIT(&ctx->list);1317 LIST_INIT(&ctx->list);
diff --git a/src/h1.c b/src/h1.c
index 3a6c1c3..73de48b 100644
--- a/src/h1.c
+++ b/src/h1.c
@@ -130,6 +130,50 @@ void h1_parse_xfer_enc_header(struct h1m *h1m, struct ist value)
130 }130 }
131}131}
132132
133/* Validate the authority and the host header value for CONNECT method. If there
134 * is hast header, its value is normalized. 0 is returned on success, -1 if the
135 * authority is invalid and -2 if the host is invalid.
136 */
137static int h1_validate_connect_authority(struct ist authority, struct ist *host_hdr)
138{
139 struct ist uri_host, uri_port, host, host_port;
140
141 if (!isttest(authority))
142 goto invalid_authority;
143 uri_host = authority;
144 uri_port = http_get_host_port(authority);
145 if (!isttest(uri_port))
146 goto invalid_authority;
147 uri_host.len -= (istlen(uri_port) + 1);
148
149 if (!host_hdr || !isttest(*host_hdr))
150 goto end;
151
152 /* Get the port of the host header value, if any */
153 host = *host_hdr;
154 host_port = http_get_host_port(*host_hdr);
155 if (isttest(host_port)) {
156 host.len -= (istlen(host_port) + 1);
157 if (!isteqi(host, uri_host) || !isteq(host_port, uri_port))
158 goto invalid_host;
159 if (http_is_default_port(IST_NULL, uri_port))
160 *host_hdr = host; /* normalize */
161 }
162 else {
163 if (!http_is_default_port(IST_NULL, uri_port) || !isteqi(host, uri_host))
164 goto invalid_host;
165 }
166
167 end:
168 return 0;
169
170 invalid_authority:
171 return -1;
172
173 invalid_host:
174 return -2;
175}
176
133/* Parse the Connection: header of an HTTP/1 request, looking for "close",177/* Parse the Connection: header of an HTTP/1 request, looking for "close",
134 * "keep-alive", and "upgrade" values, and updating h1m->flags according to178 * "keep-alive", and "upgrade" values, and updating h1m->flags according to
135 * what was found there. Note that flags are only added, not removed, so the179 * what was found there. Note that flags are only added, not removed, so the
@@ -706,6 +750,10 @@ int h1_headers_to_hdr_list(char *start, const char *stop,
706750
707 if (likely(*ptr == ':')) {751 if (likely(*ptr == ':')) {
708 col = ptr - start;752 col = ptr - start;
753 if (col <= sol) {
754 state = H1_MSG_HDR_NAME;
755 goto http_msg_invalid;
756 }
709 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_hdr_l1_sp, http_msg_ood, state, H1_MSG_HDR_L1_SP);757 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_hdr_l1_sp, http_msg_ood, state, H1_MSG_HDR_L1_SP);
710 }758 }
711759
@@ -868,22 +916,9 @@ int h1_headers_to_hdr_list(char *start, const char *stop,
868 else if (isteqi(n, ist("upgrade"))) {916 else if (isteqi(n, ist("upgrade"))) {
869 h1_parse_upgrade_header(h1m, v);917 h1_parse_upgrade_header(h1m, v);
870 }918 }
871 else if (!(h1m->flags & (H1_MF_HDRS_ONLY|H1_MF_RESP)) && isteqi(n, ist("host"))) {919 else if (!(h1m->flags & H1_MF_RESP) && isteqi(n, ist("host"))) {
872 if (host_idx == -1) {920 if (host_idx == -1)
873 struct ist authority;
874
875 authority = http_get_authority(sl.rq.u, 1);
876 if (authority.len && !isteqi(v, authority)) {
877 if (h1m->err_pos < -1) {
878 state = H1_MSG_HDR_L2_LWS;
879 ptr = v.ptr; /* Set ptr on the error */
880 goto http_msg_invalid;
881 }
882 if (h1m->err_pos == -1) /* capture the error pointer */
883 h1m->err_pos = v.ptr - start + skip; /* >= 0 now */
884 }
885 host_idx = hdr_count;921 host_idx = hdr_count;
886 }
887 else {922 else {
888 if (!isteqi(v, hdr[host_idx].v)) {923 if (!isteqi(v, hdr[host_idx].v)) {
889 state = H1_MSG_HDR_L2_LWS;924 state = H1_MSG_HDR_L2_LWS;
@@ -934,6 +969,48 @@ int h1_headers_to_hdr_list(char *start, const char *stop,
934 if (restarting)969 if (restarting)
935 goto restart;970 goto restart;
936971
972
973 if (!(h1m->flags & (H1_MF_HDRS_ONLY|H1_MF_RESP))) {
974 struct ist authority;
975
976 authority = http_get_authority(sl.rq.u, 1);
977 if (sl.rq.meth == HTTP_METH_CONNECT) {
978 struct ist *host = ((host_idx != -1) ? &hdr[host_idx].v : NULL);
979 int ret;
980
981 ret = h1_validate_connect_authority(authority, host);
982 if (ret < 0) {
983 if (h1m->err_pos < -1) {
984 state = H1_MSG_LAST_LF;
985 /* WT: gcc seems to see a path where sl.rq.u.ptr was used
986 * uninitialized, but it doesn't know that the function is
987 * called with initial states making this impossible.
988 */
989 ALREADY_CHECKED(sl.rq.u.ptr);
990 ptr = ((ret == -1) ? sl.rq.u.ptr : host->ptr); /* Set ptr on the error */
991 goto http_msg_invalid;
992 }
993 if (h1m->err_pos == -1) /* capture the error pointer */
994 h1m->err_pos = ((ret == -1) ? sl.rq.u.ptr : host->ptr) - start + skip; /* >= 0 now */
995 }
996 }
997 else if (host_idx != -1 && istlen(authority)) {
998 struct ist host = hdr[host_idx].v;
999
1000 /* For non-CONNECT method, the authority must match the host header value */
1001 if (!isteqi(authority, host)) {
1002 if (h1m->err_pos < -1) {
1003 state = H1_MSG_LAST_LF;
1004 ptr = host.ptr; /* Set ptr on the error */
1005 goto http_msg_invalid;
1006 }
1007 if (h1m->err_pos == -1) /* capture the error pointer */
1008 h1m->err_pos = v.ptr - start + skip; /* >= 0 now */
1009 }
1010
1011 }
1012 }
1013
937 state = H1_MSG_DATA;1014 state = H1_MSG_DATA;
938 if (h1m->flags & H1_MF_XFER_ENC) {1015 if (h1m->flags & H1_MF_XFER_ENC) {
939 if (h1m->flags & H1_MF_CLEN) {1016 if (h1m->flags & H1_MF_CLEN) {
diff --git a/src/h1_htx.c b/src/h1_htx.c
index b6a91f2..650acba 100644
--- a/src/h1_htx.c
+++ b/src/h1_htx.c
@@ -279,6 +279,9 @@ static int h1_postparse_res_hdrs(struct h1m *h1m, union h1_sl *h1sl, struct htx
279 goto output_full;279 goto output_full;
280 }280 }
281281
282 if ((h1m->flags & (H1_MF_CONN_UPG|H1_MF_UPG_WEBSOCKET)) && code != 101)
283 h1m->flags &= ~(H1_MF_CONN_UPG|H1_MF_UPG_WEBSOCKET);
284
282 if (((h1m->flags & H1_MF_METH_CONNECT) && code >= 200 && code < 300) || code == 101) {285 if (((h1m->flags & H1_MF_METH_CONNECT) && code >= 200 && code < 300) || code == 101) {
283 h1m->flags &= ~(H1_MF_CLEN|H1_MF_CHNK);286 h1m->flags &= ~(H1_MF_CLEN|H1_MF_CHNK);
284 h1m->flags |= H1_MF_XFER_LEN;287 h1m->flags |= H1_MF_XFER_LEN;
diff --git a/src/haproxy.c b/src/haproxy.c
index b484195..2f85293 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -1,6 +1,6 @@
1/*1/*
2 * HAProxy : High Availability-enabled HTTP/TCP proxy2 * HAProxy : High Availability-enabled HTTP/TCP proxy
3 * Copyright 2000-2022 Willy Tarreau <willy@haproxy.org>.3 * Copyright 2000-2023 Willy Tarreau <willy@haproxy.org>.
4 *4 *
5 * This program is free software; you can redistribute it and/or5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License6 * modify it under the terms of the GNU General Public License
@@ -2080,6 +2080,10 @@ static void init(int argc, char **argv)
2080 exit(1);2080 exit(1);
2081 }2081 }
20822082
2083 /* set the default maxconn in the master, but let it be rewritable with -n */
2084 if (global.mode & MODE_MWORKER_WAIT)
2085 global.maxconn = DEFAULT_MAXCONN;
2086
2083 if (cfg_maxconn > 0)2087 if (cfg_maxconn > 0)
2084 global.maxconn = cfg_maxconn;2088 global.maxconn = cfg_maxconn;
20852089
@@ -2629,7 +2633,7 @@ void run_poll_loop()
2629 if (killed > 1)2633 if (killed > 1)
2630 break;2634 break;
26312635
2632 /* expire immediately if events are pending */2636 /* expire immediately if events or signals are pending */
2633 wake = 1;2637 wake = 1;
2634 if (thread_has_tasks())2638 if (thread_has_tasks())
2635 activity[tid].wake_tasks++;2639 activity[tid].wake_tasks++;
@@ -2639,6 +2643,10 @@ void run_poll_loop()
2639 if (thread_has_tasks()) {2643 if (thread_has_tasks()) {
2640 activity[tid].wake_tasks++;2644 activity[tid].wake_tasks++;
2641 _HA_ATOMIC_AND(&sleeping_thread_mask, ~tid_bit);2645 _HA_ATOMIC_AND(&sleeping_thread_mask, ~tid_bit);
2646 } else if (signal_queue_len) {
2647 /* this check is required to avoid
2648 * a race with wakeup on signals using wake_threads() */
2649 _HA_ATOMIC_AND(&sleeping_thread_mask, ~tid_bit);
2642 } else2650 } else
2643 wake = 0;2651 wake = 0;
2644 }2652 }
diff --git a/src/hlua.c b/src/hlua.c
index 0af3eb0..aea338f 100644
--- a/src/hlua.c
+++ b/src/hlua.c
@@ -738,7 +738,11 @@ __LJMP int hlua_lua2arg_check(lua_State *L, int first, struct arg *argp,
738 break;738 break;
739739
740 case ARGT_TAB:740 case ARGT_TAB:
741 argp[idx].data.prx = p;741 if (!p->table) {
742 msg = "Mandatory argument expected";
743 goto error;
744 }
745 argp[idx].data.t = p->table;
742 argp[idx].type = ARGT_TAB;746 argp[idx].type = ARGT_TAB;
743 argp[idx+1].type = ARGT_STOP;747 argp[idx+1].type = ARGT_STOP;
744 break;748 break;
@@ -979,6 +983,7 @@ __LJMP int hlua_lua2arg_check(lua_State *L, int first, struct arg *argp,
979 return 0;983 return 0;
980984
981 error:985 error:
986 argp[idx].type = ARGT_STOP;
982 for (i = 0; i < idx; i++) {987 for (i = 0; i < idx; i++) {
983 if (argp[i].type == ARGT_STR)988 if (argp[i].type == ARGT_STR)
984 chunk_destroy(&argp[i].data.str);989 chunk_destroy(&argp[i].data.str);
@@ -4421,7 +4426,7 @@ __LJMP static int hlua_applet_http_getline_yield(lua_State *L, int status, lua_K
4421 /* The message was fully consumed and no more data are expected4426 /* The message was fully consumed and no more data are expected
4422 * (EOM flag set).4427 * (EOM flag set).
4423 */4428 */
4424 if (htx_is_empty(htx) && (htx->flags & HTX_FL_EOM))4429 if (htx_is_empty(htx) && (req->flags & CF_EOI))
4425 stop = 1;4430 stop = 1;
44264431
4427 htx_to_buf(htx, &req->buf);4432 htx_to_buf(htx, &req->buf);
@@ -4513,7 +4518,7 @@ __LJMP static int hlua_applet_http_recv_yield(lua_State *L, int status, lua_KCon
4513 /* The message was fully consumed and no more data are expected4518 /* The message was fully consumed and no more data are expected
4514 * (EOM flag set).4519 * (EOM flag set).
4515 */4520 */
4516 if (htx_is_empty(htx) && (htx->flags & HTX_FL_EOM))4521 if (htx_is_empty(htx) && (req->flags & CF_EOI))
4517 len = 0;4522 len = 0;
45184523
4519 htx_to_buf(htx, &req->buf);4524 htx_to_buf(htx, &req->buf);
diff --git a/src/hlua_fcn.c b/src/hlua_fcn.c
index 26aa509..010bd13 100644
--- a/src/hlua_fcn.c
+++ b/src/hlua_fcn.c
@@ -1305,6 +1305,7 @@ int hlua_proxy_pause(lua_State *L)
1305 struct proxy *px;1305 struct proxy *px;
13061306
1307 px = hlua_check_proxy(L, 1);1307 px = hlua_check_proxy(L, 1);
1308 /* safe to call without PROXY_LOCK - pause_proxy takes it */
1308 pause_proxy(px);1309 pause_proxy(px);
1309 return 0;1310 return 0;
1310}1311}
@@ -1314,6 +1315,7 @@ int hlua_proxy_resume(lua_State *L)
1314 struct proxy *px;1315 struct proxy *px;
13151316
1316 px = hlua_check_proxy(L, 1);1317 px = hlua_check_proxy(L, 1);
1318 /* safe to call without PROXY_LOCK - resume_proxy takes it */
1317 resume_proxy(px);1319 resume_proxy(px);
1318 return 0;1320 return 0;
1319}1321}
@@ -1323,6 +1325,7 @@ int hlua_proxy_stop(lua_State *L)
1323 struct proxy *px;1325 struct proxy *px;
13241326
1325 px = hlua_check_proxy(L, 1);1327 px = hlua_check_proxy(L, 1);
1328 /* safe to call without PROXY_LOCK - stop_proxy takes it */
1326 stop_proxy(px);1329 stop_proxy(px);
1327 return 0;1330 return 0;
1328}1331}
diff --git a/src/hpack-dec.c b/src/hpack-dec.c
index 4fa9bfd..ed39007 100644
--- a/src/hpack-dec.c
+++ b/src/hpack-dec.c
@@ -32,6 +32,7 @@
3232
33#include <import/ist.h>33#include <import/ist.h>
34#include <haproxy/chunk.h>34#include <haproxy/chunk.h>
35#include <haproxy/global.h>
35#include <haproxy/h2.h>36#include <haproxy/h2.h>
36#include <haproxy/hpack-dec.h>37#include <haproxy/hpack-dec.h>
37#include <haproxy/hpack-huff.h>38#include <haproxy/hpack-huff.h>
@@ -419,6 +420,15 @@ int hpack_decode_frame(struct hpack_dht *dht, const uint8_t *raw, uint32_t len,
419 /* <name> and <value> are correctly filled here */420 /* <name> and <value> are correctly filled here */
420 }421 }
421422
423 /* We must not accept empty header names (forbidden by the spec and used
424 * as a list termination).
425 */
426 if (!name.len) {
427 hpack_debug_printf("##ERR@%d##\n", __LINE__);
428 ret = -HPACK_ERR_INVALID_ARGUMENT;
429 goto leave;
430 }
431
422 /* here's what we have here :432 /* here's what we have here :
423 * - name.len > 0433 * - name.len > 0
424 * - value is filled with either const data or data allocated from tmp434 * - value is filled with either const data or data allocated from tmp
diff --git a/src/http.c b/src/http.c
index 0b00e47..c10b433 100644
--- a/src/http.c
+++ b/src/http.c
@@ -468,6 +468,38 @@ const char *http_get_reason(unsigned int status)
468 }468 }
469}469}
470470
471/* Returns the ist string corresponding to port part (without ':') in the host
472 * <host> or IST_NULL if not found.
473*/
474struct ist http_get_host_port(const struct ist host)
475{
476 char *start, *end, *ptr;
477
478 start = istptr(host);
479 end = istend(host);
480 for (ptr = end; ptr > start && isdigit((unsigned char)*--ptr););
481
482 /* no port found */
483 if (likely(*ptr != ':' || ptr+1 == end || ptr == start))
484 return IST_NULL;
485
486 return istnext(ist2(ptr, end - ptr));
487}
488
489
490/* Return non-zero if the port <port> is a default port. If the scheme <schm> is
491 * set, it is used to detect default ports (HTTP => 80 and HTTPS => 443)
492 * port. Otherwise, both are considered as default ports.
493 */
494int http_is_default_port(const struct ist schm, const struct ist port)
495{
496 if (!isttest(schm))
497 return (isteq(port, ist("443")) || isteq(port, ist("80")));
498 else
499 return (isteq(port, ist("443")) && isteqi(schm, ist("https://"))) ||
500 (isteq(port, ist("80")) && isteqi(schm, ist("http://")));
501}
502
471/* Returns non-zero if the scheme <schm> is syntactically correct according to503/* Returns non-zero if the scheme <schm> is syntactically correct according to
472 * RFC3986#3.1, otherwise zero. It expects only the scheme and nothing else504 * RFC3986#3.1, otherwise zero. It expects only the scheme and nothing else
473 * (particularly not the following "://").505 * (particularly not the following "://").
diff --git a/src/http_act.c b/src/http_act.c
index f88c856..59e614f 100644
--- a/src/http_act.c
+++ b/src/http_act.c
@@ -1877,6 +1877,8 @@ static void release_http_redir(struct act_rule *rule)
1877 free(redir->cookie_str);1877 free(redir->cookie_str);
1878 list_for_each_entry_safe(lf, lfb, &redir->rdr_fmt, list) {1878 list_for_each_entry_safe(lf, lfb, &redir->rdr_fmt, list) {
1879 LIST_DELETE(&lf->list);1879 LIST_DELETE(&lf->list);
1880 release_sample_expr(lf->expr);
1881 free(lf->arg);
1880 free(lf);1882 free(lf);
1881 }1883 }
1882 free(redir);1884 free(redir);
diff --git a/src/http_ana.c b/src/http_ana.c
index 4491ea1..2e2095b 100644
--- a/src/http_ana.c
+++ b/src/http_ana.c
@@ -938,9 +938,8 @@ int http_wait_for_request_body(struct stream *s, struct channel *req, int an_bit
938{938{
939 struct session *sess = s->sess;939 struct session *sess = s->sess;
940 struct http_txn *txn = s->txn;940 struct http_txn *txn = s->txn;
941 struct http_msg *msg = &s->txn->req;
942941
943 DBG_TRACE_ENTER(STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn, msg);942 DBG_TRACE_ENTER(STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn, &s->txn->req);
944943
945944
946 switch (http_wait_for_msg_body(s, req, s->be->timeout.httpreq, 0)) {945 switch (http_wait_for_msg_body(s, req, s->be->timeout.httpreq, 0)) {
@@ -998,7 +997,7 @@ int http_wait_for_request_body(struct stream *s, struct channel *req, int an_bit
998 if (!(s->flags & SF_ERR_MASK))997 if (!(s->flags & SF_ERR_MASK))
999 s->flags |= SF_ERR_PRXCOND;998 s->flags |= SF_ERR_PRXCOND;
1000 if (!(s->flags & SF_FINST_MASK))999 if (!(s->flags & SF_FINST_MASK))
1001 s->flags |= (msg->msg_state < HTTP_MSG_DATA ? SF_FINST_R : SF_FINST_D);1000 s->flags |= SF_FINST_R;
10021001
1003 req->analysers &= AN_REQ_FLT_END;1002 req->analysers &= AN_REQ_FLT_END;
1004 req->analyse_exp = TICK_ETERNITY;1003 req->analyse_exp = TICK_ETERNITY;
@@ -2655,17 +2654,21 @@ static enum rule_result http_req_restrict_header_names(struct stream *s, struct
26552654
2656 if (type == HTX_BLK_HDR) {2655 if (type == HTX_BLK_HDR) {
2657 struct ist n = htx_get_blk_name(htx, blk);2656 struct ist n = htx_get_blk_name(htx, blk);
2658 int i;2657 int i, end = istlen(n);
26592658
2660 for (i = 0; i < istlen(n); i++) {2659 for (i = 0; i < end; i++) {
2661 if (!isalnum((unsigned char)n.ptr[i]) && n.ptr[i] != '-') {2660 if (!isalnum((unsigned char)n.ptr[i]) && n.ptr[i] != '-') {
2662 /* Block the request or remove the header */2661 break;
2663 if (px->options2 & PR_O2_RSTRICT_REQ_HDR_NAMES_BLK)
2664 goto block;
2665 blk = htx_remove_blk(htx, blk);
2666 continue;
2667 }2662 }
2668 }2663 }
2664
2665 if (i < end) {
2666 /* Disallowed character found - block the request or remove the header */
2667 if (px->options2 & PR_O2_RSTRICT_REQ_HDR_NAMES_BLK)
2668 goto block;
2669 blk = htx_remove_blk(htx, blk);
2670 continue;
2671 }
2669 }2672 }
2670 if (type == HTX_BLK_EOH)2673 if (type == HTX_BLK_EOH)
2671 break;2674 break;
@@ -2778,6 +2781,7 @@ int http_res_set_status(unsigned int status, struct ist reason, struct stream *s
27782781
2779 if (!http_replace_res_status(htx, ist2(trash.area, trash.data), reason))2782 if (!http_replace_res_status(htx, ist2(trash.area, trash.data), reason))
2780 return -1;2783 return -1;
2784 s->txn->status = status;
2781 return 0;2785 return 0;
2782}2786}
27832787
@@ -4241,7 +4245,7 @@ enum rule_result http_wait_for_msg_body(struct stream *s, struct channel *chn,
4241 if (!(s->flags & SF_ERR_MASK))4245 if (!(s->flags & SF_ERR_MASK))
4242 s->flags |= SF_ERR_CLITO;4246 s->flags |= SF_ERR_CLITO;
4243 if (!(s->flags & SF_FINST_MASK))4247 if (!(s->flags & SF_FINST_MASK))
4244 s->flags |= SF_FINST_D;4248 s->flags |= SF_FINST_R;
4245 _HA_ATOMIC_INC(&sess->fe->fe_counters.failed_req);4249 _HA_ATOMIC_INC(&sess->fe->fe_counters.failed_req);
4246 if (sess->listener && sess->listener->counters)4250 if (sess->listener && sess->listener->counters)
4247 _HA_ATOMIC_INC(&sess->listener->counters->failed_req);4251 _HA_ATOMIC_INC(&sess->listener->counters->failed_req);
@@ -4254,7 +4258,7 @@ enum rule_result http_wait_for_msg_body(struct stream *s, struct channel *chn,
4254 if (!(s->flags & SF_ERR_MASK))4258 if (!(s->flags & SF_ERR_MASK))
4255 s->flags |= SF_ERR_SRVTO;4259 s->flags |= SF_ERR_SRVTO;
4256 if (!(s->flags & SF_FINST_MASK))4260 if (!(s->flags & SF_FINST_MASK))
4257 s->flags |= SF_FINST_D;4261 s->flags |= SF_FINST_R;
4258 stream_inc_http_fail_ctr(s);4262 stream_inc_http_fail_ctr(s);
4259 http_reply_and_close(s, txn->status, http_error_message(s));4263 http_reply_and_close(s, txn->status, http_error_message(s));
4260 ret = HTTP_RULE_RES_ABRT;4264 ret = HTTP_RULE_RES_ABRT;
@@ -5205,8 +5209,10 @@ struct http_txn *http_create_txn(struct stream *s)
52055209
5206 txn->auth.method = HTTP_AUTH_UNKNOWN;5210 txn->auth.method = HTTP_AUTH_UNKNOWN;
52075211
5208 vars_init(&s->vars_txn, SCOPE_TXN);5212 /* here we don't want to re-initialize s->vars_txn and s->vars_reqres
5209 vars_init(&s->vars_reqres, SCOPE_REQ);5213 * variable lists, because they were already initialized upon stream
5214 * creation in stream_new(), and thus may already contain some variables
5215 */
52105216
5211 return txn;5217 return txn;
5212}5218}
diff --git a/src/http_fetch.c b/src/http_fetch.c
index 3950eea..6678c85 100644
--- a/src/http_fetch.c
+++ b/src/http_fetch.c
@@ -222,7 +222,7 @@ struct htx *smp_prefetch_htx(struct sample *smp, struct channel *chn, struct che
222 if (IS_HTX_STRM(s)) {222 if (IS_HTX_STRM(s)) {
223 htx = htxbuf(&chn->buf);223 htx = htxbuf(&chn->buf);
224224
225 if (msg->msg_state == HTTP_MSG_ERROR || (htx->flags & HTX_FL_PARSING_ERROR))225 if (htx->flags & HTX_FL_PARSING_ERROR)
226 return NULL;226 return NULL;
227227
228 if (msg->msg_state < HTTP_MSG_BODY) {228 if (msg->msg_state < HTTP_MSG_BODY) {
@@ -307,7 +307,7 @@ struct htx *smp_prefetch_htx(struct sample *smp, struct channel *chn, struct che
307 if (txn->meth == HTTP_METH_GET || txn->meth == HTTP_METH_HEAD)307 if (txn->meth == HTTP_METH_GET || txn->meth == HTTP_METH_HEAD)
308 s->flags |= SF_REDIRECTABLE;308 s->flags |= SF_REDIRECTABLE;
309 }309 }
310 else310 else if (txn->status == -1)
311 txn->status = sl->info.res.status;311 txn->status = sl->info.res.status;
312 if (sl->flags & HTX_SL_F_VER_11)312 if (sl->flags & HTX_SL_F_VER_11)
313 msg->flags |= HTTP_MSGF_VER_11;313 msg->flags |= HTTP_MSGF_VER_11;
@@ -330,20 +330,21 @@ static int smp_fetch_meth(const struct arg *args, struct sample *smp, const char
330{330{
331 struct channel *chn = SMP_REQ_CHN(smp);331 struct channel *chn = SMP_REQ_CHN(smp);
332 struct http_txn *txn;332 struct http_txn *txn;
333 struct htx *htx;333 struct htx *htx = NULL;
334 int meth;334 int meth;
335335
336 txn = (smp->strm ? smp->strm->txn : NULL);336 txn = (smp->strm ? smp->strm->txn : NULL);
337 if (!txn)337 if (!txn)
338 return 0;338 return 0;
339339
340 if (txn->meth == HTTP_METH_OTHER) {340 meth = txn->meth;
341 if (meth == HTTP_METH_OTHER) {
341 htx = smp_prefetch_htx(smp, chn, NULL, 1);342 htx = smp_prefetch_htx(smp, chn, NULL, 1);
342 if (!htx)343 if (!htx)
343 return 0;344 return 0;
345 meth = txn->meth;
344 }346 }
345347
346 meth = txn->meth;
347 smp->data.type = SMP_T_METH;348 smp->data.type = SMP_T_METH;
348 smp->data.u.meth.meth = meth;349 smp->data.u.meth.meth = meth;
349 if (meth == HTTP_METH_OTHER) {350 if (meth == HTTP_METH_OTHER) {
diff --git a/src/http_htx.c b/src/http_htx.c
index 6f5c1a1..60525bb 100644
--- a/src/http_htx.c
+++ b/src/http_htx.c
@@ -388,6 +388,9 @@ int http_replace_req_uri(struct htx *htx, const struct ist uri)
388 goto fail;388 goto fail;
389389
390 sl = http_get_stline(htx);390 sl = http_get_stline(htx);
391 ALREADY_CHECKED(sl); /* the stline exists because http_replace_stline() succeded */
392 sl->flags &= ~HTX_SL_F_NORMALIZED_URI;
393
391 if (!http_update_host(htx, sl, uri))394 if (!http_update_host(htx, sl, uri))
392 goto fail;395 goto fail;
393396
@@ -918,7 +921,7 @@ int http_str_to_htx(struct buffer *buf, struct ist raw, char **errmsg)
918 ret = h1_headers_to_hdr_list(raw.ptr, raw.ptr + raw.len,921 ret = h1_headers_to_hdr_list(raw.ptr, raw.ptr + raw.len,
919 hdrs, sizeof(hdrs)/sizeof(hdrs[0]), &h1m, &h1sl);922 hdrs, sizeof(hdrs)/sizeof(hdrs[0]), &h1m, &h1sl);
920 if (ret <= 0) {923 if (ret <= 0) {
921 memprintf(errmsg, "unabled to parse headers (error offset: %d)", h1m.err_pos);924 memprintf(errmsg, "unable to parse headers (error offset: %d)", h1m.err_pos);
922 goto error;925 goto error;
923 }926 }
924927
@@ -1565,6 +1568,7 @@ struct http_reply *http_parse_http_reply(const char **args, int *orig_arg, struc
1565 fd = -1;1568 fd = -1;
1566 obj[objlen] = '\0';1569 obj[objlen] = '\0';
1567 reply->type = HTTP_REPLY_LOGFMT;1570 reply->type = HTTP_REPLY_LOGFMT;
1571 LIST_INIT(&reply->body.fmt);
1568 cur_arg++;1572 cur_arg++;
1569 }1573 }
1570 else if (strcmp(args[cur_arg], "lf-string") == 0) {1574 else if (strcmp(args[cur_arg], "lf-string") == 0) {
@@ -1581,6 +1585,7 @@ struct http_reply *http_parse_http_reply(const char **args, int *orig_arg, struc
1581 obj = strdup(args[cur_arg]);1585 obj = strdup(args[cur_arg]);
1582 objlen = strlen(args[cur_arg]);1586 objlen = strlen(args[cur_arg]);
1583 reply->type = HTTP_REPLY_LOGFMT;1587 reply->type = HTTP_REPLY_LOGFMT;
1588 LIST_INIT(&reply->body.fmt);
1584 cur_arg++;1589 cur_arg++;
1585 }1590 }
1586 else if (strcmp(args[cur_arg], "hdr") == 0) {1591 else if (strcmp(args[cur_arg], "hdr") == 0) {
@@ -1721,12 +1726,6 @@ struct http_reply *http_parse_http_reply(const char **args, int *orig_arg, struc
1721 return NULL;1726 return NULL;
1722}1727}
17231728
1724static int uri_is_default_port(const struct ist scheme, const struct ist port)
1725{
1726 return (isteq(port, ist("443")) && isteqi(scheme, ist("https://"))) ||
1727 (isteq(port, ist("80")) && isteqi(scheme, ist("http://")));
1728}
1729
1730/* Apply schemed-based normalization as described on rfc3986 on section 6.3.2.1729/* Apply schemed-based normalization as described on rfc3986 on section 6.3.2.
1731 * Returns 0 if no error has been found else non-zero.1730 * Returns 0 if no error has been found else non-zero.
1732 *1731 *
@@ -1741,7 +1740,6 @@ int http_scheme_based_normalize(struct htx *htx)
1741 struct http_hdr_ctx ctx;1740 struct http_hdr_ctx ctx;
1742 struct htx_sl *sl;1741 struct htx_sl *sl;
1743 struct ist uri, scheme, authority, host, port;1742 struct ist uri, scheme, authority, host, port;
1744 char *start, *end, *ptr;
17451743
1746 sl = http_get_stline(htx);1744 sl = http_get_stline(htx);
17471745
@@ -1755,25 +1753,16 @@ int http_scheme_based_normalize(struct htx *htx)
1755 if (!isttest(scheme))1753 if (!isttest(scheme))
1756 return 0;1754 return 0;
17571755
1758 /* Extract the port if present in authority. To properly support ipv61756 /* Extract the port if present in authority */
1759 * hostnames, do a reverse search on the last ':' separator as long as1757 authority = http_get_authority(uri, 1);
1760 * digits are found.1758 port = http_get_host_port(authority);
1761 */1759 if (!isttest(port)) {
1762 authority = http_get_authority(uri, 0);1760 /* if no port found, no normalization to proceed */
1763 start = istptr(authority);
1764 end = istend(authority);
1765 for (ptr = end; ptr > start && isdigit((unsigned char)*--ptr); )
1766 ;
1767
1768 /* if no port found, no normalization to proceed */
1769 if (likely(*ptr != ':'))
1770 return 0;1761 return 0;
1762 }
1763 host = isttrim(authority, istlen(authority) - istlen(port) - 1);
17711764
1772 /* split host/port on the ':' separator found */1765 if (istlen(port) && http_is_default_port(scheme, port)) {
1773 host = ist2(start, ptr - start);
1774 port = istnext(ist2(ptr, end - ptr));
1775
1776 if (istlen(port) && uri_is_default_port(scheme, port)) {
1777 /* reconstruct the uri with removal of the port */1766 /* reconstruct the uri with removal of the port */
1778 struct buffer *temp = get_trash_chunk();1767 struct buffer *temp = get_trash_chunk();
1779 struct ist meth, vsn;1768 struct ist meth, vsn;
diff --git a/src/listener.c b/src/listener.c
index 0ffd0fe..67616f5 100644
--- a/src/listener.c
+++ b/src/listener.c
@@ -45,6 +45,7 @@ static struct bind_kw_list bind_keywords = {
45/* list of the temporarily limited listeners because of lack of resource */45/* list of the temporarily limited listeners because of lack of resource */
46static struct mt_list global_listener_queue = MT_LIST_HEAD_INIT(global_listener_queue);46static struct mt_list global_listener_queue = MT_LIST_HEAD_INIT(global_listener_queue);
47static struct task *global_listener_queue_task;47static struct task *global_listener_queue_task;
48__decl_thread(static HA_RWLOCK_T global_listener_rwlock);
4849
49/* listener status for stats */50/* listener status for stats */
50const char* li_status_st[LI_STATE_COUNT] = {51const char* li_status_st[LI_STATE_COUNT] = {
@@ -297,13 +298,14 @@ void enable_listener(struct listener *listener)
297298
298/*299/*
299 * This function completely stops a listener. It will need to operate under the300 * This function completely stops a listener. It will need to operate under the
300 * proxy's lock, the protocol's lock, and the listener's lock. The caller is301 * It will need to operate under the proxy's lock and the protocol's lock.
301 * responsible for indicating in lpx, lpr, lli whether the respective locks are302 * The caller is responsible for indicating in lpx, lpr whether the
302 * already held (non-zero) or not (zero) so that the function picks the missing303 * respective locks are already held (non-zero) or not (zero) so that the
303 * ones, in this order. The proxy's listeners count is updated and the proxy is304 * function picks the missing ones, in this order.
305 * The proxy's listeners count is updated and the proxy is
304 * disabled and woken up after the last one is gone.306 * disabled and woken up after the last one is gone.
305 */307 */
306void stop_listener(struct listener *l, int lpx, int lpr, int lli)308void stop_listener(struct listener *l, int lpx, int lpr)
307{309{
308 struct proxy *px = l->bind_conf->frontend;310 struct proxy *px = l->bind_conf->frontend;
309311
@@ -320,8 +322,7 @@ void stop_listener(struct listener *l, int lpx, int lpr, int lli)
320 if (!lpr)322 if (!lpr)
321 HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);323 HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
322324
323 if (!lli)325 HA_RWLOCK_WRLOCK(LISTENER_LOCK, &l->lock);
324 HA_RWLOCK_WRLOCK(LISTENER_LOCK, &l->lock);
325326
326 if (l->state > LI_INIT) {327 if (l->state > LI_INIT) {
327 do_unbind_listener(l);328 do_unbind_listener(l);
@@ -332,8 +333,7 @@ void stop_listener(struct listener *l, int lpx, int lpr, int lli)
332 proxy_cond_disable(px);333 proxy_cond_disable(px);
333 }334 }
334335
335 if (!lli)336 HA_RWLOCK_WRUNLOCK(LISTENER_LOCK, &l->lock);
336 HA_RWLOCK_WRUNLOCK(LISTENER_LOCK, &l->lock);
337337
338 if (!lpr)338 if (!lpr)
339 HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);339 HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
@@ -422,12 +422,18 @@ int default_resume_listener(struct listener *l)
422 * closes upon SHUT_WR and refuses to rebind. So a common validation path422 * closes upon SHUT_WR and refuses to rebind. So a common validation path
423 * involves SHUT_WR && listen && SHUT_RD. In case of success, the FD's polling423 * involves SHUT_WR && listen && SHUT_RD. In case of success, the FD's polling
424 * is disabled. It normally returns non-zero, unless an error is reported.424 * is disabled. It normally returns non-zero, unless an error is reported.
425 * It will need to operate under the proxy's lock. The caller is
426 * responsible for indicating in lpx whether the proxy locks is
427 * already held (non-zero) or not (zero) so that the function picks it.
425 */428 */
426int pause_listener(struct listener *l)429int pause_listener(struct listener *l, int lpx)
427{430{
428 struct proxy *px = l->bind_conf->frontend;431 struct proxy *px = l->bind_conf->frontend;
429 int ret = 1;432 int ret = 1;
430433
434 if (!lpx)
435 HA_RWLOCK_WRLOCK(PROXY_LOCK, &px->lock);
436
431 HA_RWLOCK_WRLOCK(LISTENER_LOCK, &l->lock);437 HA_RWLOCK_WRLOCK(LISTENER_LOCK, &l->lock);
432438
433 if ((global.mode & (MODE_DAEMON | MODE_MWORKER)) &&439 if ((global.mode & (MODE_DAEMON | MODE_MWORKER)) &&
@@ -450,6 +456,10 @@ int pause_listener(struct listener *l)
450 }456 }
451 end:457 end:
452 HA_RWLOCK_WRUNLOCK(LISTENER_LOCK, &l->lock);458 HA_RWLOCK_WRUNLOCK(LISTENER_LOCK, &l->lock);
459
460 if (!lpx)
461 HA_RWLOCK_WRUNLOCK(PROXY_LOCK, &px->lock);
462
453 return ret;463 return ret;
454}464}
455465
@@ -462,13 +472,19 @@ int pause_listener(struct listener *l)
462 * state, it's totally rebound. This can happen if a pause() has completely472 * state, it's totally rebound. This can happen if a pause() has completely
463 * stopped it. If the resume fails, 0 is returned and an error might be473 * stopped it. If the resume fails, 0 is returned and an error might be
464 * displayed.474 * displayed.
475 * It will need to operate under the proxy's lock. The caller is
476 * responsible for indicating in lpx whether the proxy locks is
477 * already held (non-zero) or not (zero) so that the function picks it.
465 */478 */
466int resume_listener(struct listener *l)479int resume_listener(struct listener *l, int lpx)
467{480{
468 struct proxy *px = l->bind_conf->frontend;481 struct proxy *px = l->bind_conf->frontend;
469 int was_paused = px && px->li_paused;482 int was_paused = px && px->li_paused;
470 int ret = 1;483 int ret = 1;
471484
485 if (!lpx)
486 HA_RWLOCK_WRLOCK(PROXY_LOCK, &px->lock);
487
472 HA_RWLOCK_WRLOCK(LISTENER_LOCK, &l->lock);488 HA_RWLOCK_WRLOCK(LISTENER_LOCK, &l->lock);
473489
474 /* check that another thread didn't to the job in parallel (e.g. at the490 /* check that another thread didn't to the job in parallel (e.g. at the
@@ -484,6 +500,10 @@ int resume_listener(struct listener *l)
484 if (l->state == LI_READY)500 if (l->state == LI_READY)
485 goto end;501 goto end;
486502
503 /* the listener might have been stopped in parallel */
504 if (l->state < LI_PAUSED)
505 goto end;
506
487 if (l->rx.proto->resume)507 if (l->rx.proto->resume)
488 ret = l->rx.proto->resume(l);508 ret = l->rx.proto->resume(l);
489509
@@ -503,6 +523,10 @@ int resume_listener(struct listener *l)
503 }523 }
504 end:524 end:
505 HA_RWLOCK_WRUNLOCK(LISTENER_LOCK, &l->lock);525 HA_RWLOCK_WRUNLOCK(LISTENER_LOCK, &l->lock);
526
527 if (!lpx)
528 HA_RWLOCK_WRUNLOCK(PROXY_LOCK, &px->lock);
529
506 return ret;530 return ret;
507}531}
508532
@@ -545,7 +569,7 @@ void dequeue_all_listeners()
545 /* This cannot fail because the listeners are by definition in569 /* This cannot fail because the listeners are by definition in
546 * the LI_LIMITED state.570 * the LI_LIMITED state.
547 */571 */
548 resume_listener(listener);572 resume_listener(listener, 0);
549 }573 }
550}574}
551575
@@ -558,7 +582,7 @@ void dequeue_proxy_listeners(struct proxy *px)
558 /* This cannot fail because the listeners are by definition in582 /* This cannot fail because the listeners are by definition in
559 * the LI_LIMITED state.583 * the LI_LIMITED state.
560 */584 */
561 resume_listener(listener);585 resume_listener(listener, 0);
562 }586 }
563}587}
564588
@@ -1084,7 +1108,7 @@ void listener_accept(struct listener *l)
1084 (!tick_isset(global_listener_queue_task->expire) ||1108 (!tick_isset(global_listener_queue_task->expire) ||
1085 tick_is_expired(global_listener_queue_task->expire, now_ms))))) {1109 tick_is_expired(global_listener_queue_task->expire, now_ms))))) {
1086 /* at least one thread has to this when quitting */1110 /* at least one thread has to this when quitting */
1087 resume_listener(l);1111 resume_listener(l, 0);
10881112
1089 /* Dequeues all of the listeners waiting for a resource */1113 /* Dequeues all of the listeners waiting for a resource */
1090 dequeue_all_listeners();1114 dequeue_all_listeners();
@@ -1103,7 +1127,7 @@ void listener_accept(struct listener *l)
1103 * Let's put it to pause in this case.1127 * Let's put it to pause in this case.
1104 */1128 */
1105 if (l->rx.proto && l->rx.proto->rx_listening(&l->rx) == 0) {1129 if (l->rx.proto && l->rx.proto->rx_listening(&l->rx) == 0) {
1106 pause_listener(l);1130 pause_listener(l, 0);
1107 goto end;1131 goto end;
1108 }1132 }
11091133
@@ -1112,7 +1136,9 @@ void listener_accept(struct listener *l)
1112 * later than <expire> ahead. The listener turns to LI_LIMITED.1136 * later than <expire> ahead. The listener turns to LI_LIMITED.
1113 */1137 */
1114 limit_listener(l, &global_listener_queue);1138 limit_listener(l, &global_listener_queue);
1139 HA_RWLOCK_RDLOCK(LISTENER_LOCK, &global_listener_rwlock);
1115 task_schedule(global_listener_queue_task, expire);1140 task_schedule(global_listener_queue_task, expire);
1141 HA_RWLOCK_RDUNLOCK(LISTENER_LOCK, &global_listener_rwlock);
1116 goto end;1142 goto end;
11171143
1118 limit_proxy:1144 limit_proxy:
@@ -1141,7 +1167,7 @@ void listener_release(struct listener *l)
1141 _HA_ATOMIC_DEC(&l->thr_conn[tid]);1167 _HA_ATOMIC_DEC(&l->thr_conn[tid]);
11421168
1143 if (l->state == LI_FULL || l->state == LI_LIMITED)1169 if (l->state == LI_FULL || l->state == LI_LIMITED)
1144 resume_listener(l);1170 resume_listener(l, 0);
11451171
1146 /* Dequeues all of the listeners waiting for a resource */1172 /* Dequeues all of the listeners waiting for a resource */
1147 dequeue_all_listeners();1173 dequeue_all_listeners();
@@ -1162,6 +1188,7 @@ static int listener_queue_init()
1162 /* very simple initialization, users will queue the task if needed */1188 /* very simple initialization, users will queue the task if needed */
1163 global_listener_queue_task->context = NULL; /* not even a context! */1189 global_listener_queue_task->context = NULL; /* not even a context! */
1164 global_listener_queue_task->process = manage_global_listener_queue;1190 global_listener_queue_task->process = manage_global_listener_queue;
1191 HA_RWLOCK_INIT(&global_listener_rwlock);
11651192
1166 return 0;1193 return 0;
1167}1194}
@@ -1199,7 +1226,9 @@ struct task *manage_global_listener_queue(struct task *t, void *context, unsigne
1199 dequeue_all_listeners();1226 dequeue_all_listeners();
12001227
1201 out:1228 out:
1229 HA_RWLOCK_WRLOCK(LISTENER_LOCK, &global_listener_rwlock);
1202 t->expire = TICK_ETERNITY;1230 t->expire = TICK_ETERNITY;
1231 HA_RWLOCK_WRUNLOCK(LISTENER_LOCK, &global_listener_rwlock);
1203 task_queue(t);1232 task_queue(t);
1204 return t;1233 return t;
1205}1234}
diff --git a/src/log.c b/src/log.c
index c431937..fbc8a2f 100644
--- a/src/log.c
+++ b/src/log.c
@@ -1381,17 +1381,21 @@ char *lf_text_len(char *dst, const char *src, size_t len, size_t size, const str
1381 }1381 }
13821382
1383 if (src && len) {1383 if (src && len) {
1384 if (++len > size)1384 /* escape_string and strlcpy2 will both try to add terminating NULL-byte
1385 len = size;1385 * to dst, so we need to make sure that extra byte will fit into dst
1386 * before calling them
1387 */
1386 if (node->options & LOG_OPT_ESC) {1388 if (node->options & LOG_OPT_ESC) {
1387 char *ret;1389 char *ret;
13881390
1389 ret = escape_string(dst, dst + len, '\\', rfc5424_escape_map, src);1391 ret = escape_string(dst, (dst + size - 1), '\\', rfc5424_escape_map, src, src + len);
1390 if (ret == NULL || *ret != '\0')1392 if (ret == NULL || *ret != '\0')
1391 return NULL;1393 return NULL;
1392 len = ret - dst;1394 len = ret - dst;
1393 }1395 }
1394 else {1396 else {
1397 if (++len > size)
1398 len = size;
1395 len = strlcpy2(dst, src, len);1399 len = strlcpy2(dst, src, len);
1396 }1400 }
13971401
@@ -1402,6 +1406,7 @@ char *lf_text_len(char *dst, const char *src, size_t len, size_t size, const str
1402 if (size < 2)1406 if (size < 2)
1403 return NULL;1407 return NULL;
1404 *(dst++) = '-';1408 *(dst++) = '-';
1409 size -= 1;
1405 }1410 }
14061411
1407 if (node->options & LOG_OPT_QUOTE) {1412 if (node->options & LOG_OPT_QUOTE) {
@@ -1877,7 +1882,7 @@ static inline void __do_send_log(struct logsrv *logsrv, int nblogger, int level,
1877 if (msg.len > logsrv->maxlen)1882 if (msg.len > logsrv->maxlen)
1878 msg.len = logsrv->maxlen;1883 msg.len = logsrv->maxlen;
18791884
1880 sent = sink_write(logsrv->sink, &msg, 1, level, logsrv->facility, metadata);1885 sent = sink_write(logsrv->sink, &msg, 1, level, facility, metadata);
1881 }1886 }
1882 else if (logsrv->addr.ss_family == AF_CUST_EXISTING_FD) {1887 else if (logsrv->addr.ss_family == AF_CUST_EXISTING_FD) {
1883 struct ist msg;1888 struct ist msg;
@@ -3418,6 +3423,7 @@ void parse_log_message(char *buf, size_t buflen, int *level, int *facility,
3418 */3423 */
34193424
3420 p += 2;3425 p += 2;
3426 *size -= 2;
3421 /* timestamp is NILVALUE '-' */3427 /* timestamp is NILVALUE '-' */
3422 if (*size > 2 && (p[0] == '-') && p[1] == ' ') {3428 if (*size > 2 && (p[0] == '-') && p[1] == ' ') {
3423 metadata[LOG_META_TIME] = ist2(p, 1);3429 metadata[LOG_META_TIME] = ist2(p, 1);
@@ -3811,7 +3817,7 @@ static void syslog_io_handler(struct appctx *appctx)
3811 if (buf->area[to_skip - 1] != ' ')3817 if (buf->area[to_skip - 1] != ' ')
3812 goto parse_error;3818 goto parse_error;
38133819
3814 msglen = strtol(trash.area, &p, 10);3820 msglen = strtol(buf->area, &p, 10);
3815 if (!msglen || p != &buf->area[to_skip - 1])3821 if (!msglen || p != &buf->area[to_skip - 1])
3816 goto parse_error;3822 goto parse_error;
38173823
diff --git a/src/mux_fcgi.c b/src/mux_fcgi.c
index d916496..7334b56 100644
--- a/src/mux_fcgi.c
+++ b/src/mux_fcgi.c
@@ -1399,7 +1399,7 @@ static int fcgi_set_default_param(struct fcgi_conn *fconn, struct fcgi_strm *fst
1399 * captured1399 * captured
1400 */1400 */
1401 params->scriptname = ist2(path.ptr + pmatch[1].rm_so, pmatch[1].rm_eo - pmatch[1].rm_so);1401 params->scriptname = ist2(path.ptr + pmatch[1].rm_so, pmatch[1].rm_eo - pmatch[1].rm_so);
1402 if (!(params->mask & FCGI_SP_PATH_INFO) && (pmatch[2].rm_so == -1 || pmatch[2].rm_eo == -1))1402 if (!(params->mask & FCGI_SP_PATH_INFO) && !(pmatch[2].rm_so == -1 || pmatch[2].rm_eo == -1))
1403 params->pathinfo = ist2(path.ptr + pmatch[2].rm_so, pmatch[2].rm_eo - pmatch[2].rm_so);1403 params->pathinfo = ist2(path.ptr + pmatch[2].rm_so, pmatch[2].rm_eo - pmatch[2].rm_so);
14041404
1405 check_index:1405 check_index:
@@ -2188,9 +2188,10 @@ static size_t fcgi_strm_send_stdin(struct fcgi_conn *fconn, struct fcgi_strm *fs
2188 size = htx_get_blksz(blk);2188 size = htx_get_blksz(blk);
2189 if (unlikely(size == count && htx_nbblks(htx) == 1 && type == HTX_BLK_DATA)) {2189 if (unlikely(size == count && htx_nbblks(htx) == 1 && type == HTX_BLK_DATA)) {
2190 void *old_area = mbuf->area;2190 void *old_area = mbuf->area;
2191 int eom = (htx->flags & HTX_FL_EOM);
21912192
2192 /* Last block of the message: Reserve the size for the empty stdin record */2193 /* Last block of the message: Reserve the size for the empty stdin record */
2193 if (htx->flags & HTX_FL_EOM)2194 if (eom)
2194 extra_bytes = FCGI_RECORD_HEADER_SZ;2195 extra_bytes = FCGI_RECORD_HEADER_SZ;
21952196
2196 if (b_data(mbuf)) {2197 if (b_data(mbuf)) {
@@ -2226,6 +2227,8 @@ static size_t fcgi_strm_send_stdin(struct fcgi_conn *fconn, struct fcgi_strm *fs
22262227
2227 htx = (struct htx *)buf->area;2228 htx = (struct htx *)buf->area;
2228 htx_reset(htx);2229 htx_reset(htx);
2230 if (eom)
2231 goto empty_stdin;
2229 goto end;2232 goto end;
2230 }2233 }
22312234
@@ -2275,7 +2278,9 @@ static size_t fcgi_strm_send_stdin(struct fcgi_conn *fconn, struct fcgi_strm *fs
2275 b_data(&outbuf) + v.len + extra_bytes <= b_room(mbuf) &&2278 b_data(&outbuf) + v.len + extra_bytes <= b_room(mbuf) &&
2276 b_data(mbuf) <= MAX_DATA_REALIGN)2279 b_data(mbuf) <= MAX_DATA_REALIGN)
2277 goto realign_again;2280 goto realign_again;
2278 v.len = b_room(&outbuf) - FCGI_RECORD_HEADER_SZ - extra_bytes;2281 v.len = (FCGI_RECORD_HEADER_SZ + extra_bytes > b_room(&outbuf)
2282 ? 0
2283 : b_room(&outbuf) - FCGI_RECORD_HEADER_SZ - extra_bytes);
2279 }2284 }
2280 if (!v.len || !chunk_memcat(&outbuf, v.ptr, v.len)) {2285 if (!v.len || !chunk_memcat(&outbuf, v.ptr, v.len)) {
2281 if (outbuf.data == FCGI_RECORD_HEADER_SZ)2286 if (outbuf.data == FCGI_RECORD_HEADER_SZ)
@@ -2306,6 +2311,7 @@ static size_t fcgi_strm_send_stdin(struct fcgi_conn *fconn, struct fcgi_strm *fs
23062311
2307 /* Send the empty stding here to finish the message */2312 /* Send the empty stding here to finish the message */
2308 if (htx_is_empty(htx) && (htx->flags & HTX_FL_EOM)) {2313 if (htx_is_empty(htx) && (htx->flags & HTX_FL_EOM)) {
2314 empty_stdin:
2309 TRACE_PROTO("sending FCGI STDIN record", FCGI_EV_TX_RECORD|FCGI_EV_TX_STDIN, fconn->conn, fstrm, htx);2315 TRACE_PROTO("sending FCGI STDIN record", FCGI_EV_TX_RECORD|FCGI_EV_TX_STDIN, fconn->conn, fstrm, htx);
2310 if (!fcgi_strm_send_empty_stdin(fconn, fstrm)) {2316 if (!fcgi_strm_send_empty_stdin(fconn, fstrm)) {
2311 /* bytes already reserved for this record. It should not fail */2317 /* bytes already reserved for this record. It should not fail */
@@ -4184,14 +4190,14 @@ static int fcgi_show_fd(struct buffer *msg, struct connection *conn)
4184 if (fstrm->cs)4190 if (fstrm->cs)
4185 chunk_appendf(msg, " .cs.flg=0x%08x .cs.data=%p",4191 chunk_appendf(msg, " .cs.flg=0x%08x .cs.data=%p",
4186 fstrm->cs->flags, fstrm->cs->data);4192 fstrm->cs->flags, fstrm->cs->data);
4187 chunk_appendf(&trash, " .subs=%p", fstrm->subs);4193 chunk_appendf(msg, " .subs=%p", fstrm->subs);
4188 if (fstrm->subs) {4194 if (fstrm->subs) {
4189 chunk_appendf(&trash, "(ev=%d tl=%p", fstrm->subs->events, fstrm->subs->tasklet);4195 chunk_appendf(msg, "(ev=%d tl=%p", fstrm->subs->events, fstrm->subs->tasklet);
4190 chunk_appendf(&trash, " tl.calls=%d tl.ctx=%p tl.fct=",4196 chunk_appendf(msg, " tl.calls=%d tl.ctx=%p tl.fct=",
4191 fstrm->subs->tasklet->calls,4197 fstrm->subs->tasklet->calls,
4192 fstrm->subs->tasklet->context);4198 fstrm->subs->tasklet->context);
4193 resolve_sym_name(&trash, NULL, fstrm->subs->tasklet->process);4199 resolve_sym_name(msg, NULL, fstrm->subs->tasklet->process);
4194 chunk_appendf(&trash, ")");4200 chunk_appendf(msg, ")");
4195 }4201 }
4196 }4202 }
4197 return 0;4203 return 0;
diff --git a/src/mux_h1.c b/src/mux_h1.c
index 8d5de5e..c29c4ed 100644
--- a/src/mux_h1.c
+++ b/src/mux_h1.c
@@ -2133,7 +2133,7 @@ static size_t h1_process_output(struct h1c *h1c, struct buffer *buf, size_t coun
2133 /* EOM flag is set or empty payload (C-L to 0) and it is the last block */2133 /* EOM flag is set or empty payload (C-L to 0) and it is the last block */
2134 if (htx_is_unique_blk(chn_htx, blk) &&2134 if (htx_is_unique_blk(chn_htx, blk) &&
2135 ((chn_htx->flags & HTX_FL_EOM) || ((h1m->flags & H1_MF_CLEN) && !h1m->curr_len))) {2135 ((chn_htx->flags & HTX_FL_EOM) || ((h1m->flags & H1_MF_CLEN) && !h1m->curr_len))) {
2136 if (h1m->flags & H1_MF_CHNK) {2136 if ((h1m->flags & H1_MF_CHNK) && !(h1s->flags & H1S_F_BODYLESS_RESP)) {
2137 if (!chunk_memcat(&tmp, "\r\n0\r\n\r\n", 7))2137 if (!chunk_memcat(&tmp, "\r\n0\r\n\r\n", 7))
2138 goto full;2138 goto full;
2139 }2139 }
@@ -2556,9 +2556,10 @@ static int h1_handle_req_tout(struct h1c *h1c)
2556 _HA_ATOMIC_INC(&sess->listener->counters->failed_req);2556 _HA_ATOMIC_INC(&sess->listener->counters->failed_req);
25572557
2558 h1c->errcode = 408;2558 h1c->errcode = 408;
2559 ret = h1_send_error(h1c);
2559 if (b_data(&h1c->ibuf) || !(sess->fe->options & PR_O_NULLNOLOG))2560 if (b_data(&h1c->ibuf) || !(sess->fe->options & PR_O_NULLNOLOG))
2560 ret = h1_send_error(h1c);
2561 sess_log(sess);
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches