Merge ~lucaskanashiro/ubuntu/+source/haproxy:jammy-mre into ubuntu/+source/haproxy:ubuntu/jammy-devel
- Git
- lp:~lucaskanashiro/ubuntu/+source/haproxy
- jammy-mre
- Merge into ubuntu/jammy-devel
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | git-ubuntu bot | ||||
Approved revision: | not available | ||||
Merge reported by: | Lucas Kanashiro | ||||
Merged at revision: | 72681649158930cfa0da398b0215df767debd077 | ||||
Proposed branch: | ~lucaskanashiro/ubuntu/+source/haproxy:jammy-mre | ||||
Merge into: | ubuntu/+source/haproxy:ubuntu/jammy-devel | ||||
Diff against target: |
7019 lines (+2604/-830) 120 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 (+24/-0) debian/patches/haproxy.service-start-after-syslog.patch (+0/-2) debian/patches/reproducible.patch (+1/-3) debian/patches/series (+0/-3) debian/tests/control (+8/-0) debian/tests/proxy-localhost (+4/-9) debian/tests/proxy-ssl-pass-through (+59/-0) debian/tests/proxy-ssl-termination (+48/-0) debian/tests/utils (+58/-0) 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) |
||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
git-ubuntu bot | Approve | ||
Andreas Hasenack | Approve | ||
Canonical Server Reporter | Pending | ||
Review via email: mp+439426@code.launchpad.net |
Commit message
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:/
autopkgtest summary:
autopkgtest [18:37:20]: @@@@@@@
cli PASS
proxy-localhost PASS
Andreas Hasenack (ahasenack) wrote : | # |
Andreas Hasenack (ahasenack) : | # |
Lucas Kanashiro (lucaskanashiro) : | # |
Lucas Kanashiro (lucaskanashiro) wrote : | # |
Fixed. Up for review again.
Andreas Hasenack (ahasenack) wrote : | # |
One inline question about the version, and another question here: have you thought about pulling in the new kinetic DEP8 tests? After all, both jammy and kinetic are receiving the same haproxy upstream version after this. Considering these are MREs, I think it would be nice to have those tests here too, unless it's too involved.
- 6944eb2... by Lucas Kanashiro
-
Backport DEP-8 tests from lunar
Lucas Kanashiro (lucaskanashiro) wrote : | # |
I fixed the version string as we discussed in the other MP and backported the DEP-8 tests as you suggested, all tests passed:
autopkgtest [16:59:13]: @@@@@@@
cli PASS
proxy-localhost PASS
proxy-ssl-
proxy-ssl-
Andreas Hasenack (ahasenack) wrote : | # |
haha, gotta love version strings :)
And thanks for bringing in the DEP8 tests
+1
git-ubuntu bot (git-ubuntu-bot) wrote : | # |
Approvers: lucaskanashiro, ahasenack
Uploaders: lucaskanashiro, ahasenack
MP auto-approved
Lucas Kanashiro (lucaskanashiro) wrote : | # |
Thanks Andreas. Package uploaded:
Uploading haproxy_
Uploading haproxy_
Uploading haproxy_
Uploading haproxy_
Preview Diff
1 | diff --git a/.cirrus.yml b/.cirrus.yml |
2 | index e754f83..deace96 100644 |
3 | --- a/.cirrus.yml |
4 | +++ b/.cirrus.yml |
5 | @@ -1,7 +1,7 @@ |
6 | FreeBSD_task: |
7 | freebsd_instance: |
8 | matrix: |
9 | - image_family: freebsd-13-0 |
10 | + image_family: freebsd-13-1 |
11 | only_if: $CIRRUS_BRANCH =~ 'master|next' |
12 | install_script: |
13 | - pkg update -f && pkg upgrade -y && pkg install -y openssl git gmake lua53 socat pcre |
14 | diff --git a/.github/matrix.py b/.github/matrix.py |
15 | index 264a3d2..abd6caf 100644 |
16 | --- a/.github/matrix.py |
17 | +++ b/.github/matrix.py |
18 | @@ -10,6 +10,7 @@ import json |
19 | import sys |
20 | import urllib.request |
21 | import re |
22 | +from os import environ |
23 | |
24 | if len(sys.argv) == 2: |
25 | build_type = sys.argv[1] |
26 | @@ -40,7 +41,7 @@ def determine_latest_openssl(ssl): |
27 | if "openssl-" in name: |
28 | if name > latest_tag: |
29 | latest_tag = name |
30 | - return "OPENSSL={}".format(latest_tag[8:]) |
31 | + return "OPENSSL_VERSION={}".format(latest_tag[8:]) |
32 | |
33 | def determine_latest_libressl(ssl): |
34 | libressl_download_list = urllib.request.urlopen("http://ftp.openbsd.org/pub/OpenBSD/LibreSSL/") |
35 | @@ -48,7 +49,7 @@ def determine_latest_libressl(ssl): |
36 | decoded_line = line.decode("utf-8") |
37 | if "libressl-" in decoded_line and ".tar.gz.asc" in decoded_line: |
38 | l = re.split("libressl-|.tar.gz.asc", decoded_line)[1] |
39 | - return "LIBRESSL={}".format(l) |
40 | + return "LIBRESSL_VERSION={}".format(l) |
41 | |
42 | def clean_compression(compression): |
43 | return compression.replace("USE_", "").lower() |
44 | @@ -67,7 +68,7 @@ matrix = [] |
45 | |
46 | # Ubuntu |
47 | |
48 | -os = "ubuntu-latest" |
49 | +os = "ubuntu-20.04" |
50 | TARGET = "linux-glibc" |
51 | for CC in ["gcc", "clang"]: |
52 | matrix.append( |
53 | @@ -125,8 +126,8 @@ for CC in ["gcc", "clang"]: |
54 | for ssl in [ |
55 | "stock", |
56 | "OPENSSL_VERSION=1.0.2u", |
57 | - "OPENSSL_VERSION=latest", |
58 | - "LIBRESSL_VERSION=latest", |
59 | + "OPENSSL_VERSION=3.0.2", |
60 | + "LIBRESSL_VERSION=3.5.3", |
61 | # "BORINGSSL=yes", |
62 | ]: |
63 | flags = ["USE_OPENSSL=1"] |
64 | @@ -155,7 +156,7 @@ for CC in ["gcc", "clang"]: |
65 | |
66 | # ASAN |
67 | |
68 | -os = "ubuntu-latest" |
69 | +os = "ubuntu-20.04" |
70 | TARGET = "linux-glibc" |
71 | for CC in ["gcc","clang"]: |
72 | matrix.append( |
73 | @@ -207,4 +208,6 @@ for CC in ["clang"]: |
74 | |
75 | print(json.dumps(matrix, indent=4, sort_keys=True)) |
76 | |
77 | -print("::set-output name=matrix::{}".format(json.dumps({"include": matrix}))) |
78 | +if environ.get('GITHUB_OUTPUT') is not None: |
79 | + with open(environ.get('GITHUB_OUTPUT'), 'a') as f: |
80 | + print("matrix={}".format(json.dumps({"include": matrix})), file=f) |
81 | diff --git a/.github/workflows/compliance.yml b/.github/workflows/compliance.yml |
82 | index 66bc154..a11f0fa 100644 |
83 | --- a/.github/workflows/compliance.yml |
84 | +++ b/.github/workflows/compliance.yml |
85 | @@ -24,7 +24,7 @@ jobs: |
86 | curl -fsSL https://github.com/summerwind/h2spec/releases/download/${H2SPEC_VERSION}/h2spec_linux_amd64.tar.gz -o h2spec.tar.gz |
87 | tar xvf h2spec.tar.gz |
88 | sudo install -m755 h2spec /usr/local/bin/h2spec |
89 | - echo "::set-output name=version::${H2SPEC_VERSION}" |
90 | + echo "version=${H2SPEC_VERSION}" >> $GITHUB_OUTPUT |
91 | - name: Compile HAProxy with ${{ matrix.CC }} |
92 | run: | |
93 | make -j$(nproc) all \ |
94 | @@ -47,7 +47,7 @@ jobs: |
95 | fi |
96 | echo "::endgroup::" |
97 | haproxy -vv |
98 | - echo "::set-output name=version::$(haproxy -v |awk 'NR==1{print $3}')" |
99 | + echo "version=$(haproxy -v |awk 'NR==1{print $3}')" >> $GITHUB_OUTPUT |
100 | - name: Launch HAProxy ${{ steps.show-version.outputs.version }} |
101 | run: haproxy -f .github/h2spec.config -D |
102 | - name: Run h2spec ${{ steps.install-h2spec.outputs.version }} |
103 | diff --git a/.github/workflows/cross-zoo.yml b/.github/workflows/cross-zoo.yml |
104 | new file mode 100644 |
105 | index 0000000..e2a5816 |
106 | --- /dev/null |
107 | +++ b/.github/workflows/cross-zoo.yml |
108 | @@ -0,0 +1,110 @@ |
109 | +# |
110 | +# this is naamed "zoo" after OpenSSL "cross zoo pipeline" |
111 | +# |
112 | +name: Cross Compile |
113 | + |
114 | +on: |
115 | + schedule: |
116 | + - cron: "0 0 21 * *" |
117 | + |
118 | +permissions: |
119 | + contents: read |
120 | + |
121 | +jobs: |
122 | + cross-compilation: |
123 | + strategy: |
124 | + matrix: |
125 | + platform: [ |
126 | + { |
127 | + arch: aarch64-linux-gnu, |
128 | + libs: libc6-dev-arm64-cross, |
129 | + target: linux-aarch64 |
130 | + }, { |
131 | + arch: alpha-linux-gnu, |
132 | + libs: libc6.1-dev-alpha-cross, |
133 | + target: linux-alpha-gcc |
134 | + }, { |
135 | + arch: arm-linux-gnueabi, |
136 | + libs: libc6-dev-armel-cross, |
137 | + target: linux-armv4 |
138 | + }, { |
139 | + arch: arm-linux-gnueabihf, |
140 | + libs: libc6-dev-armhf-cross, |
141 | + target: linux-armv4 |
142 | + }, { |
143 | + arch: hppa-linux-gnu, |
144 | + libs: libc6-dev-hppa-cross, |
145 | + target: -static linux-generic32 |
146 | + }, { |
147 | + arch: m68k-linux-gnu, |
148 | + libs: libc6-dev-m68k-cross, |
149 | + target: -static -m68040 linux-latomic |
150 | + }, { |
151 | + arch: mips-linux-gnu, |
152 | + libs: libc6-dev-mips-cross, |
153 | + target: -static linux-mips32 |
154 | + }, { |
155 | + arch: mips64-linux-gnuabi64, |
156 | + libs: libc6-dev-mips64-cross, |
157 | + target: -static linux64-mips64 |
158 | + }, { |
159 | + arch: mipsel-linux-gnu, |
160 | + libs: libc6-dev-mipsel-cross, |
161 | + target: linux-mips32 |
162 | + }, { |
163 | + arch: powerpc64le-linux-gnu, |
164 | + libs: libc6-dev-ppc64el-cross, |
165 | + target: linux-ppc64le |
166 | + }, { |
167 | + arch: riscv64-linux-gnu, |
168 | + libs: libc6-dev-riscv64-cross, |
169 | + target: linux64-riscv64 |
170 | + }, { |
171 | + arch: s390x-linux-gnu, |
172 | + libs: libc6-dev-s390x-cross, |
173 | + target: linux64-s390x |
174 | + }, { |
175 | + arch: sh4-linux-gnu, |
176 | + libs: libc6-dev-sh4-cross, |
177 | + target: no-async linux-latomic |
178 | + }, { |
179 | + arch: hppa-linux-gnu, |
180 | + libs: libc6-dev-hppa-cross, |
181 | + target: linux-generic32, |
182 | + }, { |
183 | + arch: m68k-linux-gnu, |
184 | + libs: libc6-dev-m68k-cross, |
185 | + target: -mcfv4e linux-latomic |
186 | + }, { |
187 | + arch: mips-linux-gnu, |
188 | + libs: libc6-dev-mips-cross, |
189 | + target: linux-mips32 |
190 | + }, { |
191 | + arch: mips64-linux-gnuabi64, |
192 | + libs: libc6-dev-mips64-cross, |
193 | + target: linux64-mips64 |
194 | + }, { |
195 | + arch: sparc64-linux-gnu, |
196 | + libs: libc6-dev-sparc64-cross, |
197 | + target: linux64-sparcv9 |
198 | + } |
199 | + ] |
200 | + runs-on: ubuntu-latest |
201 | + steps: |
202 | + - name: install packages |
203 | + run: | |
204 | + sudo apt-get update |
205 | + sudo apt-get -yq --force-yes install \ |
206 | + gcc-${{ matrix.platform.arch }} \ |
207 | + ${{ matrix.platform.libs }} |
208 | + - uses: actions/checkout@v2 |
209 | + |
210 | + |
211 | + - name: install quictls |
212 | + run: | |
213 | + QUICTLS_EXTRA_ARGS="--cross-compile-prefix=${{ matrix.platform.arch }}- ${{ matrix.platform.target }}" QUICTLS=yes scripts/build-ssl.sh |
214 | + |
215 | + - name: Build |
216 | + run: | |
217 | + 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" |
218 | + |
219 | diff --git a/.github/workflows/vtest.yml b/.github/workflows/vtest.yml |
220 | index ea39662..781a2b3 100644 |
221 | --- a/.github/workflows/vtest.yml |
222 | +++ b/.github/workflows/vtest.yml |
223 | @@ -50,7 +50,7 @@ jobs: |
224 | - name: Generate cache key |
225 | id: generate-cache-key |
226 | run: | |
227 | - echo "::set-output name=key::$(echo ${{ matrix.name }} | sha256sum | awk '{print $1}')" |
228 | + echo "key=$(echo ${{ matrix.name }} | sha256sum | awk '{print $1}')" >> $GITHUB_OUTPUT |
229 | |
230 | - name: Cache SSL libs |
231 | if: ${{ matrix.ssl && matrix.ssl != 'stock' && matrix.ssl != 'BORINGSSL=yes' && matrix.ssl != 'QUICTLS=yes' }} |
232 | @@ -114,6 +114,9 @@ jobs: |
233 | run: make -C addons/wurfl/dummy |
234 | - name: Compile HAProxy with ${{ matrix.CC }} |
235 | run: | |
236 | + echo "::group::Show compiler's version" |
237 | + echo | ${{ matrix.CC }} -v |
238 | + echo "::endgroup::" |
239 | echo "::group::Show platform specific defines" |
240 | echo | ${{ matrix.CC }} -dM -xc -E - |
241 | echo "::endgroup::" |
242 | @@ -138,7 +141,7 @@ jobs: |
243 | fi |
244 | echo "::endgroup::" |
245 | haproxy -vv |
246 | - echo "::set-output name=version::$(haproxy -v |awk 'NR==1{print $3}')" |
247 | + echo "version=$(haproxy -v |awk 'NR==1{print $3}')" >> $GITHUB_OUTPUT |
248 | - name: Install problem matcher for VTest |
249 | # This allows one to more easily see which tests fail. |
250 | run: echo "::add-matcher::.github/vtest.json" |
251 | diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml |
252 | index 58283ff..022c7f6 100644 |
253 | --- a/.github/workflows/windows.yml |
254 | +++ b/.github/workflows/windows.yml |
255 | @@ -56,9 +56,10 @@ jobs: |
256 | TARGET=${{ matrix.TARGET }} \ |
257 | CC=${{ matrix.CC }} \ |
258 | DEBUG="-DDEBUG_STRICT -DDEBUG_MEMORY_POOLS -DDEBUG_POOL_INTEGRITY" \ |
259 | + DEBUG_CFLAGS="-g -Wno-deprecated-declarations" \ |
260 | ${{ join(matrix.FLAGS, ' ') }} |
261 | - name: Show HAProxy version |
262 | id: show-version |
263 | run: | |
264 | ./haproxy -vv |
265 | - echo "::set-output name=version::$(./haproxy -v |awk 'NR==1{print $3}')" |
266 | + echo "version=$(./haproxy -v |awk 'NR==1{print $3}')" >> $GITHUB_OUTPUT |
267 | diff --git a/CHANGELOG b/CHANGELOG |
268 | index f9eec74..d59309f 100644 |
269 | --- a/CHANGELOG |
270 | +++ b/CHANGELOG |
271 | @@ -1,6 +1,196 @@ |
272 | ChangeLog : |
273 | =========== |
274 | |
275 | +2023/02/14 : 2.4.22 |
276 | + - BUG/MINOR: fcgi-app: prevent 'use-fcgi-app' in default section |
277 | + - BUG/MEDIUM: ssl: wrong eviction from the session cache tree |
278 | + - BUG/MINOR: ssl/crt-list: warn when a line is malformated |
279 | + - BUG/MEDIUM: stick-table: do not leave entries in end of window during purge |
280 | + - BUG/MEDIUM: cache: use the correct time reference when comparing dates |
281 | + - DOC: config: fix option spop-check proxy compatibility |
282 | + - DOC: config: 'http-send-name-header' option may be used in default section |
283 | + - DOC: proxy-protocol: fix wrong byte in provided example |
284 | + - BUG/MEDIUM: stconn: Schedule a shutw on shutr if data must be sent first |
285 | + - CI: github: don't warn on deprecated openssl functions on windows |
286 | + - BUG/CRITICAL: http: properly reject empty http header field names |
287 | + |
288 | +2023/01/27 : 2.4.21 |
289 | + - BUG/MINOR: http-htx: Don't consider an URI as normalized after a set-uri action |
290 | + - BUG/MEDIIM: stconn: Flush output data before forwarding close to write side |
291 | + - CI: github: change "ubuntu-latest" to "ubuntu-20.04" |
292 | + - BUILD: peers: peers-t.h depends on stick-table-t.h |
293 | + - BUG/MINOR: resolvers: Don't wait periodic resolution on healthcheck failure |
294 | + - BUG/MEDIUM: ssl: Verify error codes can exceed 63 |
295 | + - BUG/MINOR: ssl: Fix potential overflow |
296 | + - BUG/MEDIUM: mworker: fix segv in early failure of mworker mode with peers |
297 | + - BUG/MINOR: promex: create haproxy_backend_agg_server_status |
298 | + - MINOR: promex: introduce haproxy_backend_agg_check_status |
299 | + - DOC: promex: Add missing backend metrics |
300 | + - BUG/MAJOR: fcgi: Fix uninitialized reserved bytes |
301 | + - REGTESTS: fix the race conditions in iff.vtc |
302 | + - REGTESTS: startup: check maxconn computation |
303 | + - BUG/MEDIUM: resolvers: Use tick_first() to update the resolvers task timeout |
304 | + - LICENSE: wurfl: clarify the dummy library license. |
305 | + - BUG/MINOR: ssl: Fix memory leak of find_chain in ssl_sock_load_cert_chain |
306 | + - BUG/MEDIUM: mux-h2: Refuse interim responses with end-stream flag set |
307 | + - BUG/MINOR: pool/stats: Use ullong to report total pool usage in bytes in stats |
308 | + - BUILD: makefile: build the features list dynamically |
309 | + - BUILD: makefile: sort the features list |
310 | + - BUG/MINOR: http-fetch: Only fill txn status during prefetch if not already set |
311 | + - BUG/MAJOR: buf: Fix copy of wrapping output data when a buffer is realigned |
312 | + - REGTEST: fix the race conditions in json_query.vtc |
313 | + - REGTEST: fix the race conditions in digest.vtc |
314 | + - REGTEST: fix the race conditions in hmac.vtc |
315 | + - BUG/MINOR: http: Memory leak of http redirect rules' format string |
316 | + - CLEANUP: htx: fix a typo in an error message of http_str_to_htx |
317 | + - BUG/MINOR: h1-htx: Remove flags about protocol upgrade on non-101 responses |
318 | + - BUG/MINOR: resolvers: Wait the resolution execution for a do_resolv action |
319 | + - BUG/MINOR: promex: Don't forget to consume the request on error |
320 | + - BUG/MINOR: http-ana: Report SF_FINST_R flag on error waiting the request body |
321 | + - BUG/MINOR: http-fetch: Don't block HTTP sample fetch eval in HTTP_MSG_ERROR state |
322 | + - BUG/MINOR: http-ana: make set-status also update txn->status |
323 | + - BUG/MINOR: listeners: fix suspend/resume of inherited FDs |
324 | + - DOC: config: fix wrong section number for "protocol prefixes" |
325 | + - DOC: config: fix aliases for protocol prefixes "udp4@" and "udp6@" |
326 | + - BUG/MINOR: mux-fcgi: Correctly set pathinfo |
327 | + - DOC: config: fix "Address formats" chapter syntax |
328 | + - BUG/MINOR: listener: close tiny race between resume_listener() and stopping |
329 | + - BUG/MINOR: mux-h2: add missing traces on failed headers decoding |
330 | + - BUILD: hpack: include global.h for the trash that is needed in debug mode |
331 | + - BUG/MINOR: sink: free the forwarding task on exit |
332 | + |
333 | +2022/12/09 : 2.4.20 |
334 | + - BUG/MINOR: checks: update pgsql regex on auth packet |
335 | + - DOC: config: Fix pgsql-check documentation to make user param mandatory |
336 | + - BUG/MEDIUM: lua: Don't crash in hlua_lua2arg_check on failure |
337 | + - BUG/MEDIUM: lua: handle stick table implicit arguments right. |
338 | + - BUILD: h1: silence an initiialized warning with gcc-4.7 and -Os |
339 | + - BUG/MINOR: http-fetch: Update method after a prefetch in smp_fetch_meth() |
340 | + - BUILD: http_fetch: silence an uninitiialized warning with gcc-4/5/6 at -Os |
341 | + - BUG/MINOR: mux-h1: Account consumed output data on synchronous connection error |
342 | + - MINOR: smtpchk: Update expect rule to fully match replies to EHLO commands |
343 | + - BUG/MINOR: smtpchk: SMTP Service check should gracefully close SMTP transaction |
344 | + - BUG/MINOR: backend: only enforce turn-around state when not redispatching |
345 | + - DOC: configuration: missing 'if' in tcp-request content example |
346 | + - BUG/MAJOR: stick-tables: do not try to index a server name for applets |
347 | + - BUG/MINOR: server: make sure "show servers state" hides private bits |
348 | + - CI: Replace the deprecated `::set-output` command by writing to $GITHUB_OUTPUT in matrix.py |
349 | + - CI: Replace the deprecated `::set-output` command by writing to $GITHUB_OUTPUT in workflow definition |
350 | + - BUG/MINOR: log: Preserve message facility when the log target is a ring buffer |
351 | + - BUG/MINOR: ring: Properly parse connect timeout |
352 | + - BUG/MEDIUM: compression: handle rewrite errors when updating response headers |
353 | + - BUG/MINOR: sink: Only use backend capability for the sink proxies |
354 | + - BUG/MINOR: sink: Set default connect/server timeout for implicit ring buffers |
355 | + - CI: SSL: use proper version generating when "latest" semantic is used |
356 | + - CI: SSL: temporarily stick to LibreSSL=3.5.3 |
357 | + - BUG/MINOR: stick-table: Use server_id instead of std_t_sint in process_store_rules() |
358 | + - DOC: management: add forgotten "show startup-logs" |
359 | + - BUG/MAJOR: stick-table: don't process store-response rules for applets |
360 | + - BUG/MEDIUM: stick-table: fix a race condition when updating the expiration task |
361 | + - BUG/MINOR: log: fixing bug in tcp syslog_io_handler Octet-Counting |
362 | + - CI: add monthly gcc cross compile jobs |
363 | + - BUG/MINOR: ssl: Memory leak of AUTHORITY_KEYID struct when loading issuer |
364 | + - BUG/MINOR: ssl: ocsp structure not freed properly in case of error |
365 | + - CI: switch to the "latest" LibreSSL |
366 | + - CI: emit the compiler's version in the build reports |
367 | + - BUG/MEDIUM: wdt/clock: properly handle early task hangs |
368 | + - BUG/MINOR: http-htx: Fix error handling during parsing http replies |
369 | + - BUG/MINOR: resolvers: Set port before IP address when processing SRV records |
370 | + - BUG/MINOR: mux-fcgi: Be sure to send empty STDING record in case of zero-copy |
371 | + - BUG/MEDIUM: mux-fcgi: Avoid value length overflow when it doesn't fit at once |
372 | + - BUG/MINOR: mux-h1: Do not send a last null chunk on body-less answers |
373 | + - REG-TESTS: cache: Remove T-E header for 304-Not-Modified responses |
374 | + - DOC: config: fix alphabetical ordering of global section |
375 | + - BUG/MEDIUM: ring: fix creation of server in uninitialized ring |
376 | + - BUG/MINOR: pool/cli: use ullong to report total pool usage in bytes |
377 | + - BUG/MEDIUM: listener: Fix race condition when updating the global mngmt task |
378 | + - BUG/MINOR: http_ana/txn: don't re-initialize txn and req var lists |
379 | + - BUG/MINOR: ssl: don't initialize the keylog callback when not required |
380 | + - BUG/MEDIUM: peers: messages about unkown tables not correctly ignored |
381 | + - BUILD: peers: Remove unused variables |
382 | + - BUG/MINOR: server/idle: at least use atomic stores when updating max_used_conns |
383 | + - BUILD: listener: fix build warning on global_listener_rwlock without threads |
384 | + - BUG/MINOR: cfgparse-listen: fix ebpt_next_dup pointer dereference on proxy "from" inheritance |
385 | + - BUG/MINOR: log: fix parse_log_message rfc5424 size check |
386 | + - BUG/MINOR: http-htx: Don't consider an URI as normalized after a set-uri action |
387 | + - BUILD: http-htx: Silent build error about a possible NULL start-line |
388 | + - BUG/MINOR: mux-h1: Fix handling of 408-Request-Time-Out |
389 | + - Revert "BUG/MINOR: http-htx: Don't consider an URI as normalized after a set-uri action" |
390 | + - DOC: config: provide some configuration hints for "http-reuse" |
391 | + - DOC: config: clarify the fact that SNI should not be used in HTTP scenarios |
392 | + - DOC: config: mention that a single monitor-uri rule is supported |
393 | + - DOC: config: explain how default matching method for ACL works |
394 | + - DOC: config: clarify the fact that "retries" is not just for connections |
395 | + - DOC: config: clarify the -m dir and -m dom pattern matching methods |
396 | + - SCRIPTS: announce-release: add a link to the data plane API |
397 | + - Revert "CI: switch to the "latest" LibreSSL" |
398 | + - Revert "CI: determine actual OpenSSL version dynamically" |
399 | + |
400 | +2022/09/28 : 2.4.19 |
401 | + - BUG/MEDIUM: mworker: use default maxconn in wait mode |
402 | + - MINOR: http: Add function to get port part of a host |
403 | + - MINOR: http: Add function to detect default port |
404 | + - BUG/MEDIUM: h1: Improve authority validation for CONNCET request |
405 | + - MINOR: http-htx: Use new HTTP functions for the scheme based normalization |
406 | + - MINOR: ebtree: add ebmb_lookup_shorter() to pursue lookups |
407 | + - BUG/MEDIUM: pattern: only visit equivalent nodes when skipping versions |
408 | + - MINOR: peers: Use a dedicated reconnect timeout when stopping the local peer |
409 | + - BUG/MEDIUM: peers: limit reconnect attempts of the old process on reload |
410 | + - BUG/MINOR: peers: Use right channel flag to consider the peer as connected |
411 | + - BUG/MEDIUM: dns: Properly initialize new DNS session |
412 | + - MINOR: server: Constify source server to copy its settings |
413 | + - REORG: server: Export srv_settings_cpy() function |
414 | + - BUG/MEDIUM: proxy: Perform a custom copy for default server settings |
415 | + - BUG/MINOR: ring/cli: fix a race condition between the writer and the reader |
416 | + - BUG/MINOR: sink: fix a race condition between the writer and the reader |
417 | + - BUILD: cfgparse: always defined _GNU_SOURCE for sched.h and crypt.h |
418 | + - BUG/MEDIUM: poller: use fd_delete() to release the poller pipes |
419 | + - BUG/MEDIUM: task: relax one thread consistency check in task_unlink_wq() |
420 | + - BUILD: debug: silence warning on gcc-5 |
421 | + - BUG/MEDIUM: ring: fix too lax 'size' parser |
422 | + - BUILD: http: silence an uninitialized warning affecting gcc-5 |
423 | + - BUG/MEDIUM: http-ana: fix crash or wrong header deletion by http-restrict-req-hdr-names |
424 | + - BUG/MEDIUM: mux-h2: do not fiddle with ->dsi to indicate demux is idle |
425 | + - BUG/MAJOR: log-forward: Fix log-forward proxies not fully initialized |
426 | + - BUG/MAJOR: mworker: fix infinite loop on master with no proxies. |
427 | + - BUG/MINOR: resolvers: return the correct value in resolvers_finalize_config() |
428 | + - BUG/MINOR: tcpcheck: Disable QUICKACK only if data should be sent after connect |
429 | + - REGTESTS: Fix prometheus script to perform HTTP health-checks |
430 | + - DOC: configuration: do-resolve doesn't work with a port in the string |
431 | + - BUG/MEDIUM: spoe: Properly update streams waiting for a ACK in async mode |
432 | + - BUG/MEDIUM: peers: Add connect and server timeut to peers proxy |
433 | + - BUG/MEDIUM: peers: Don't use resync timer when local resync is in progress |
434 | + - BUG/MEDIUM: peers: Don't start resync on reload if local peer is not up-to-date |
435 | + - BUG/MINOR: hlua: Rely on CF_EOI to detect end of message in HTTP applets |
436 | + - BUG/MINOR: tcpcheck: Disable QUICKACK for default tcp-check (with no rule) |
437 | + - BUG/MEDIUM: mux-h1: do not refrain from signaling errors after end of input |
438 | + - REGTESTS: http_request_buffer: Add a barrier to not mix up log messages |
439 | + - BUG/MEDIUM: mux-h1: always use RST to kill idle connections in pools |
440 | + - BUG/MINOR: mux-h2: fix the "show fd" dest buffer for the subscriber |
441 | + - BUG/MINOR: mux-h1: fix the "show fd" dest buffer for the subscriber |
442 | + - BUG/MINOR: mux-fcgi: fix the "show fd" dest buffer for the subscriber |
443 | + - BUG/MINOR: regex: Properly handle PCRE2 lib compiled without JIT support |
444 | + - BUILD: makefile: enable crypt(3) for NetBSD |
445 | + - BUG/MINOR: h1: Support headers case adjustment for TCP proxies |
446 | + - BUG/MINOR: task: always reset a new tasklet's call date |
447 | + - BUG/MINOR: signals/poller: set the poller timeout to 0 when there are signals |
448 | + - BUG/MINOR: signals/poller: ensure wakeup from signals |
449 | + - CI: cirrus-ci: bump FreeBSD image to 13-1 |
450 | + - BUG/MEDIUM: proxy: ensure pause_proxy() and resume_proxy() own PROXY_LOCK |
451 | + - MINOR: listener: small API change |
452 | + - BUG/MINOR: stats: fixing stat shows disabled frontend status as 'OPEN' |
453 | + - REGTESTS: healthcheckmail: Relax matching on the healthcheck log message |
454 | + - REGTESTS: log: test the log-forward feature |
455 | + - BUG/MEDIUM: sink: bad init sequence on tcp sink from a ring. |
456 | + - REGTESTS: ssl/log: test the log-forward with SSL |
457 | + - DOC: fix TOC in starter guide for subsection 3.3.8. Statistics |
458 | + - BUG/MEDIUM: captures: free() an error capture out of the proxy lock |
459 | + - BUILD: fd: fix a build warning on the DWCAS |
460 | + - SCRIPTS: announce-release: update some URLs to https |
461 | + - BUG/MINOR: log: improper behavior when escaping log data |
462 | + - REGTESTS: 4be_1srv_smtpchk_httpchk_layer47errors: Return valid SMTP replies |
463 | + - BUG/MEDIUM: resolvers: Remove aborted resolutions from query_ids tree |
464 | + |
465 | 2022/07/27 : 2.4.18 |
466 | - CI: determine actual LibreSSL version dynamically |
467 | - MEDIUM: http-ana: Add a proxy option to restrict chars in request header names |
468 | diff --git a/Makefile b/Makefile |
469 | index c0a6a27..40c2b10 100644 |
470 | --- a/Makefile |
471 | +++ b/Makefile |
472 | @@ -423,8 +423,8 @@ endif |
473 | # NetBSD 8 and above |
474 | ifeq ($(TARGET),netbsd) |
475 | set_target_defaults = $(call default_opts, \ |
476 | - USE_POLL USE_TPROXY USE_THREAD USE_KQUEUE USE_ACCEPT4 USE_CLOSEFROM \ |
477 | - USE_GETADDRINFO) |
478 | + USE_POLL USE_TPROXY USE_LIBCRYPT USE_THREAD USE_KQUEUE USE_ACCEPT4 \ |
479 | + USE_CLOSEFROM USE_GETADDRINFO) |
480 | endif |
481 | |
482 | # AIX 5.1 only |
483 | @@ -524,7 +524,11 @@ ignore_implicit = $(if $(subst environment,,$(origin $(1))), \ |
484 | # is used to report a list of all flags which were used to build this version. |
485 | # Do not assign anything to it. |
486 | BUILD_OPTIONS := $(foreach opt,$(use_opts),$(call ignore_implicit,$(opt))) |
487 | -BUILD_FEATURES := $(foreach opt,$(patsubst USE_%,%,$(use_opts)),$(if $(USE_$(opt)),+$(opt),-$(opt))) |
488 | + |
489 | +# Make a list of all known features with +/- prepended depending on their |
490 | +# activation status. Must be a macro so that dynamically enabled ones are |
491 | +# evaluated with their current status. |
492 | +BUILD_FEATURES = $(foreach opt,$(patsubst USE_%,%,$(sort $(use_opts))),$(if $(USE_$(opt)),+$(opt),-$(opt))) |
493 | |
494 | # All USE_* options have their equivalent macro defined in the code (some might |
495 | # possibly be unused though) |
496 | diff --git a/SUBVERS b/SUBVERS |
497 | index 994ee02..f042fd0 100644 |
498 | --- a/SUBVERS |
499 | +++ b/SUBVERS |
500 | @@ -1,2 +1,2 @@ |
501 | --1d80f18 |
502 | +-f8e3218 |
503 | |
504 | diff --git a/VERDATE b/VERDATE |
505 | index 6a4d254..d8a3372 100644 |
506 | --- a/VERDATE |
507 | +++ b/VERDATE |
508 | @@ -1,2 +1,2 @@ |
509 | -2022-07-27 15:10:44 +0200 |
510 | -2022/07/27 |
511 | +2023-02-14 16:57:13 +0100 |
512 | +2023/02/14 |
513 | diff --git a/VERSION b/VERSION |
514 | index cc2ff5a..76cb51e 100644 |
515 | --- a/VERSION |
516 | +++ b/VERSION |
517 | @@ -1 +1 @@ |
518 | -2.4.18 |
519 | +2.4.22 |
520 | diff --git a/addons/promex/README b/addons/promex/README |
521 | index e41ebdc..4e29e23 100644 |
522 | --- a/addons/promex/README |
523 | +++ b/addons/promex/README |
524 | @@ -286,6 +286,8 @@ See prometheus export for the description of each field. |
525 | | haproxy_backend_max_total_time_seconds | |
526 | | haproxy_backend_internal_errors_total | |
527 | | haproxy_backend_uweight | |
528 | +| haproxy_backend_agg_server_status | |
529 | +| haproxy_backend_agg_check_status | |
530 | +-----------------------------------------------------+ |
531 | |
532 | * Server metrics |
533 | diff --git a/addons/promex/service-prometheus.c b/addons/promex/service-prometheus.c |
534 | index b267f98..d31b666 100644 |
535 | --- a/addons/promex/service-prometheus.c |
536 | +++ b/addons/promex/service-prometheus.c |
537 | @@ -289,6 +289,8 @@ const struct promex_metric promex_st_metrics[ST_F_TOTAL_FIELDS] = { |
538 | [ST_F_NEED_CONN_EST] = { .n = IST("need_connections_current"), .type = PROMEX_MT_GAUGE, .flags = ( PROMEX_FL_SRV_METRIC) }, |
539 | [ST_F_UWEIGHT] = { .n = IST("uweight"), .type = PROMEX_MT_GAUGE, .flags = ( PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) }, |
540 | [ST_F_AGG_SRV_CHECK_STATUS] = { .n = IST("agg_server_check_status"), .type = PROMEX_MT_GAUGE, .flags = ( PROMEX_FL_BACK_METRIC ) }, |
541 | + [ST_F_AGG_SRV_STATUS ] = { .n = IST("agg_server_status"), .type = PROMEX_MT_GAUGE, .flags = ( PROMEX_FL_BACK_METRIC ) }, |
542 | + [ST_F_AGG_CHECK_STATUS] = { .n = IST("agg_check_status"), .type = PROMEX_MT_GAUGE, .flags = ( PROMEX_FL_BACK_METRIC ) }, |
543 | }; |
544 | |
545 | /* Description of overridden stats fields */ |
546 | @@ -792,6 +794,7 @@ static int promex_dump_back_metrics(struct appctx *appctx, struct htx *htx) |
547 | double secs; |
548 | enum promex_back_state bkd_state; |
549 | enum promex_srv_state srv_state; |
550 | + enum healthcheck_status srv_check_status; |
551 | |
552 | for (;appctx->st2 < ST_F_TOTAL_FIELDS; appctx->st2++) { |
553 | if (!(promex_st_metrics[appctx->st2].flags & appctx->ctx.stats.flags)) |
554 | @@ -800,6 +803,8 @@ static int promex_dump_back_metrics(struct appctx *appctx, struct htx *htx) |
555 | while (appctx->ctx.stats.obj1) { |
556 | struct promex_label labels[PROMEX_MAX_LABELS-1] = {}; |
557 | unsigned int srv_state_count[PROMEX_SRV_STATE_COUNT] = { 0 }; |
558 | + unsigned int srv_check_count[HCHK_STATUS_SIZE] = { 0 }; |
559 | + const char *check_state; |
560 | |
561 | px = appctx->ctx.stats.obj1; |
562 | |
563 | @@ -814,7 +819,8 @@ static int promex_dump_back_metrics(struct appctx *appctx, struct htx *htx) |
564 | return -1; |
565 | |
566 | switch (appctx->st2) { |
567 | - case ST_F_AGG_SRV_CHECK_STATUS: |
568 | + case ST_F_AGG_SRV_CHECK_STATUS: // DEPRECATED |
569 | + case ST_F_AGG_SRV_STATUS: |
570 | if (!px->srv) |
571 | goto next_px; |
572 | sv = px->srv; |
573 | @@ -833,6 +839,28 @@ static int promex_dump_back_metrics(struct appctx *appctx, struct htx *htx) |
574 | } |
575 | appctx->ctx.stats.st_code = 0; |
576 | goto next_px; |
577 | + case ST_F_AGG_CHECK_STATUS: |
578 | + if (!px->srv) |
579 | + goto next_px; |
580 | + sv = px->srv; |
581 | + while (sv) { |
582 | + srv_check_status = sv->check.status; |
583 | + srv_check_count[srv_check_status] += 1; |
584 | + sv = sv->next; |
585 | + } |
586 | + for (; appctx->ctx.stats.st_code < HCHK_STATUS_SIZE; appctx->ctx.stats.st_code++) { |
587 | + if (get_check_status_result(appctx->ctx.stats.st_code) < CHK_RES_FAILED) |
588 | + continue; |
589 | + val = mkf_u32(FO_STATUS, srv_check_count[appctx->ctx.stats.st_code]); |
590 | + check_state = get_check_status_info(appctx->ctx.stats.st_code); |
591 | + labels[1].name = ist("state"); |
592 | + labels[1].value = ist(check_state); |
593 | + if (!promex_dump_metric(appctx, htx, prefix, &promex_st_metrics[appctx->st2], |
594 | + &val, labels, &out, max)) |
595 | + goto full; |
596 | + } |
597 | + appctx->ctx.stats.st_code = 0; |
598 | + goto next_px; |
599 | case ST_F_STATUS: |
600 | bkd_state = ((px->lbprm.tot_weight > 0 || !px->srv) ? 1 : 0); |
601 | for (; appctx->ctx.stats.st_code < PROMEX_BACK_STATE_COUNT; appctx->ctx.stats.st_code++) { |
602 | @@ -1547,6 +1575,7 @@ static void promex_appctx_handle_io(struct appctx *appctx) |
603 | res->flags |= CF_READ_NULL; |
604 | si_shutr(si); |
605 | si_shutw(si); |
606 | + goto out; |
607 | } |
608 | |
609 | struct applet promex_applet = { |
610 | diff --git a/addons/wurfl/dummy/wurfl/wurfl.h b/addons/wurfl/dummy/wurfl/wurfl.h |
611 | index 3b450fc..7659561 100644 |
612 | --- a/addons/wurfl/dummy/wurfl/wurfl.h |
613 | +++ b/addons/wurfl/dummy/wurfl/wurfl.h |
614 | @@ -4,11 +4,16 @@ |
615 | * Copyright (c) ScientiaMobile, Inc. |
616 | * http://www.scientiamobile.com |
617 | * |
618 | - * This software package is the property of ScientiaMobile Inc. and is licensed |
619 | - * commercially according to a contract between the Licensee and ScientiaMobile Inc. (Licensor). |
620 | - * If you represent the Licensee, please refer to the licensing agreement which has been signed |
621 | - * between the two parties. If you do not represent the Licensee, you are not authorized to use |
622 | - * this software in any way. |
623 | + * This software package is the property of ScientiaMobile Inc. and is distributed under |
624 | + * a dual licensing scheme: |
625 | + * |
626 | + * 1) commercially according to a contract between the Licensee and ScientiaMobile Inc. (Licensor). |
627 | + * If you represent the Licensee, please refer to the licensing agreement which has been signed |
628 | + * between the two parties. If you do not represent the Licensee, you are not authorized to use |
629 | + * this software in any way. |
630 | + * |
631 | + * 2) LGPL when used in the context of the HAProxy project with the purpose of testing compatibility |
632 | + * of HAProxy with ScientiaMobile software. |
633 | * |
634 | */ |
635 | |
636 | diff --git a/debian/changelog b/debian/changelog |
637 | index e96c035..738a16f 100644 |
638 | --- a/debian/changelog |
639 | +++ b/debian/changelog |
640 | @@ -1,3 +1,27 @@ |
641 | +haproxy (2.4.22-0ubuntu0.22.04.1) jammy; urgency=medium |
642 | + |
643 | + * New upstream release (LP: #2012557). |
644 | + - Major and critical bug fixes according to the upstream changelog: |
645 | + + BUG/MAJOR: log-forward: Fix log-forward proxies not fully initialized |
646 | + + BUG/MAJOR: mworker: fix infinite loop on master with no proxies. |
647 | + + BUG/MAJOR: stick-tables: do not try to index a server name for applets |
648 | + + BUG/MAJOR: stick-table: don't process store-response rules for applets |
649 | + + BUG/MAJOR: fcgi: Fix uninitialized reserved bytes |
650 | + + BUG/MAJOR: buf: Fix copy of wrapping output data when a buffer is realigned |
651 | + + BUG/CRITICAL: http: properly reject empty http header field names |
652 | + - Remove patches applied by upstream in debian/patches: |
653 | + + CVE-2023-0056.patch |
654 | + + CVE-2023-25725.patch |
655 | + + CVE-2023-0836.patch |
656 | + - Refresh existing patches in debian/patches: |
657 | + + haproxy.service-start-after-syslog.patch |
658 | + + reproducible.patch |
659 | + * Backport DEP-8 tests from Lunar: |
660 | + - d/t/proxy-ssl-termination |
661 | + - d/t/proxy-ssl-pass-through |
662 | + |
663 | + -- Lucas Kanashiro <kanashiro@ubuntu.com> Wed, 22 Mar 2023 18:18:54 -0300 |
664 | + |
665 | haproxy (2.4.18-0ubuntu1.3) jammy-security; urgency=medium |
666 | |
667 | * SECURITY UPDATE: information leak via uninitialized bytes |
668 | diff --git a/debian/patches/CVE-2023-0056.patch b/debian/patches/CVE-2023-0056.patch |
669 | deleted file mode 100644 |
670 | index dd8b02d..0000000 |
671 | --- a/debian/patches/CVE-2023-0056.patch |
672 | +++ /dev/null |
673 | @@ -1,38 +0,0 @@ |
674 | -From 827a6299e6995c5c3ba620d8b7cbacdaef67f2c4 Mon Sep 17 00:00:00 2001 |
675 | -From: Christopher Faulet <cfaulet@haproxy.com> |
676 | -Date: Thu, 22 Dec 2022 09:47:01 +0100 |
677 | -Subject: [PATCH] BUG/MEDIUM: mux-h2: Refuse interim responses with end-stream |
678 | - flag set |
679 | - |
680 | -As state in RFC9113#8.1, HEADERS frame with the ES flag set that carries an |
681 | -informational status code is malformed. However, there is no test on this |
682 | -condition. |
683 | - |
684 | -On 2.4 and higher, it is hard to predict consequences of this bug because |
685 | -end of the message is only reported with a flag. But on 2.2 and lower, it |
686 | -leads to a crash because there is an unexpected extra EOM block at the end |
687 | -of an interim response. |
688 | - |
689 | -Now, when a ES flag is detected on a HEADERS frame for an interim message, a |
690 | -stream error is sent (RST_STREAM/PROTOCOL_ERROR). |
691 | - |
692 | -This patch should solve the issue #1972. It should be backported as far as |
693 | -2.0. |
694 | ---- |
695 | - src/mux_h2.c | 5 +++++ |
696 | - 1 file changed, 5 insertions(+) |
697 | - |
698 | ---- a/src/mux_h2.c |
699 | -+++ b/src/mux_h2.c |
700 | -@@ -4940,6 +4940,11 @@ next_frame: |
701 | - *flags |= H2_SF_HEADERS_RCVD; |
702 | - |
703 | - if (h2c->dff & H2_F_HEADERS_END_STREAM) { |
704 | -+ if (msgf & H2_MSGF_RSP_1XX) { |
705 | -+ /* RFC9113#8.1 : HEADERS frame with the ES flag set that carries an informational status code is malformed */ |
706 | -+ 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); |
707 | -+ goto fail; |
708 | -+ } |
709 | - /* no more data are expected for this message */ |
710 | - htx->flags |= HTX_FL_EOM; |
711 | - } |
712 | diff --git a/debian/patches/CVE-2023-0836.patch b/debian/patches/CVE-2023-0836.patch |
713 | deleted file mode 100644 |
714 | index f708696..0000000 |
715 | --- a/debian/patches/CVE-2023-0836.patch |
716 | +++ /dev/null |
717 | @@ -1,47 +0,0 @@ |
718 | -From f988992d16f45ef03d5bbb024a1042ed8123e4c5 Mon Sep 17 00:00:00 2001 |
719 | -From: Youfu Zhang <zhangyoufu@gmail.com> |
720 | -Date: Fri, 9 Dec 2022 19:15:48 +0800 |
721 | -Subject: [PATCH] BUG/MAJOR: fcgi: Fix uninitialized reserved bytes |
722 | - |
723 | -The output buffer is not zero-initialized. If we don't clear reserved |
724 | -bytes, fcgi requests sent to backend will leak sensitive data. |
725 | - |
726 | -This patch must be backported as far as 2.2. |
727 | - |
728 | -(cherry picked from commit 2e6bf0a2722866ae0128a4392fa2375bd1f03ff8) |
729 | -Signed-off-by: Christopher Faulet <cfaulet@haproxy.com> |
730 | -(cherry picked from commit db03179fee55c60a92ce6b86a0f04dbb9ba0328b) |
731 | -Signed-off-by: Christopher Faulet <cfaulet@haproxy.com> |
732 | ---- |
733 | - src/fcgi.c | 8 ++++++-- |
734 | - 1 file changed, 6 insertions(+), 2 deletions(-) |
735 | - |
736 | -diff --git a/src/fcgi.c b/src/fcgi.c |
737 | -index dcf2db2..1d1a82b 100644 |
738 | ---- a/src/fcgi.c |
739 | -+++ b/src/fcgi.c |
740 | -@@ -47,7 +47,7 @@ int fcgi_encode_record_hdr(struct buffer *out, const struct fcgi_header *h) |
741 | - out->area[len++] = ((h->len >> 8) & 0xff); |
742 | - out->area[len++] = (h->len & 0xff); |
743 | - out->area[len++] = h->padding; |
744 | -- len++; /* rsv */ |
745 | -+ out->area[len++] = 0; /* rsv */ |
746 | - |
747 | - out->data = len; |
748 | - return 1; |
749 | -@@ -94,7 +94,11 @@ int fcgi_encode_begin_request(struct buffer *out, const struct fcgi_begin_reques |
750 | - out->area[len++] = ((r->role >> 8) & 0xff); |
751 | - out->area[len++] = (r->role & 0xff); |
752 | - out->area[len++] = r->flags; |
753 | -- len += 5; /* rsv */ |
754 | -+ out->area[len++] = 0; /* rsv */ |
755 | -+ out->area[len++] = 0; |
756 | -+ out->area[len++] = 0; |
757 | -+ out->area[len++] = 0; |
758 | -+ out->area[len++] = 0; |
759 | - |
760 | - out->data = len; |
761 | - return 1; |
762 | --- |
763 | -1.7.10.4 |
764 | - |
765 | diff --git a/debian/patches/CVE-2023-25725.patch b/debian/patches/CVE-2023-25725.patch |
766 | deleted file mode 100644 |
767 | index 1897223..0000000 |
768 | --- a/debian/patches/CVE-2023-25725.patch |
769 | +++ /dev/null |
770 | @@ -1,145 +0,0 @@ |
771 | -From a6c7ac9d51248a641f456906549120d3f6387049 Mon Sep 17 00:00:00 2001 |
772 | -From: Willy Tarreau <w@1wt.eu> |
773 | -Date: Thu, 9 Feb 2023 21:36:54 +0100 |
774 | -Subject: BUG/CRITICAL: http: properly reject empty http header field names |
775 | - |
776 | -The HTTP header parsers surprizingly accepts empty header field names, |
777 | -and this is a leftover from the original code that was agnostic to this. |
778 | - |
779 | -When muxes were introduced, for H2 first, the HPACK decompressor needed |
780 | -to feed headers lists, and since empty header names were strictly |
781 | -forbidden by the protocol, the lists of headers were purposely designed |
782 | -to be terminated by an empty header field name (a principle that is |
783 | -similar to H1's empty line termination). This principle was preserved |
784 | -and generalized to other protocols migrated to muxes (H1/FCGI/H3 etc) |
785 | -without anyone ever noticing that the H1 parser was still able to deliver |
786 | -empty header field names to this list. In addition to this it turns out |
787 | -that the HPACK decompressor, despite a comment in the code, may |
788 | -successfully decompress an empty header field name, and this mistake |
789 | -was propagated to the QPACK decompressor as well. |
790 | - |
791 | -The impact is that an empty header field name may be used to truncate |
792 | -the list of headers and thus make some headers disappear. While for |
793 | -H2/H3 the impact is limited as haproxy sees a request with missing |
794 | -headers, and headers are not used to delimit messages, in the case of |
795 | -HTTP/1, the impact is significant because the presence (and sometimes |
796 | -contents) of certain sensitive headers is detected during the parsing. |
797 | -Thus, some of these headers may be seen, marked as present, their value |
798 | -extracted, but never delivered to upper layers and obviously not |
799 | -forwarded to the other side either. This can have for consequence that |
800 | -certain important header fields such as Connection, Upgrade, Host, |
801 | -Content-length, Transfer-Encoding etc are possibly seen as different |
802 | -between what haproxy uses to parse/forward/route and what is observed |
803 | -in http-request rules and of course, forwarded. One direct consequence |
804 | -is that it is possible to exploit this property in HTTP/1 to make |
805 | -affected versions of haproxy forward more data than is advertised on |
806 | -the other side, and bypass some access controls or routing rules by |
807 | -crafting extraneous requests. Note, however, that responses to such |
808 | -requests will normally not be passed back to the client, but this can |
809 | -still cause some harm. |
810 | - |
811 | -This specific risk can be mostly worked around in configuration using |
812 | -the following rule that will rely on the bug's impact to precisely |
813 | -detect the inconsistency between the known body size and the one |
814 | -expected to be advertised to the server (the rule works from 2.0 to |
815 | -2.8-dev): |
816 | - |
817 | - 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 } |
818 | - |
819 | -This will exclusively block such carefully crafted requests delivered |
820 | -over HTTP/1. HTTP/2 and HTTP/3 do not need content-length, and a body |
821 | -that arrives without being announced with a content-length will be |
822 | -forwarded using transfer-encoding, hence will not cause discrepancies. |
823 | -In HAProxy 2.0 in legacy mode ("no option http-use-htx"), this rule will |
824 | -simply have no effect but will not cause trouble either. |
825 | - |
826 | -A clean solution would consist in modifying the loops iterating over |
827 | -these headers lists to check the header name's pointer instead of its |
828 | -length (since both are zero at the end of the list), but this requires |
829 | -to touch tens of places and it's very easy to miss one. Functions such |
830 | -as htx_add_header(), htx_add_trailer(), htx_add_all_headers() would be |
831 | -good starting points for such a possible future change. |
832 | - |
833 | -Instead the current fix focuses on blocking empty headers where they |
834 | -are first inserted, hence in the H1/HPACK/QPACK decoders. One benefit |
835 | -of the current solution (for H1) is that it allows "show errors" to |
836 | -report a precise diagnostic when facing such invalid HTTP/1 requests, |
837 | -with the exact location of the problem and the originating address: |
838 | - |
839 | - $ printf "GET / HTTP/1.1\r\nHost: localhost\r\n:empty header\r\n\r\n" | nc 0 8001 |
840 | - HTTP/1.1 400 Bad request |
841 | - Content-length: 90 |
842 | - Cache-Control: no-cache |
843 | - Connection: close |
844 | - Content-Type: text/html |
845 | - |
846 | - <html><body><h1>400 Bad request</h1> |
847 | - Your browser sent an invalid request. |
848 | - </body></html> |
849 | - |
850 | - $ socat /var/run/haproxy.stat <<< "show errors" |
851 | - Total events captured on [10/Feb/2023:16:29:37.530] : 1 |
852 | - |
853 | - [10/Feb/2023:16:29:34.155] frontend decrypt (#2): invalid request |
854 | - backend <NONE> (#-1), server <NONE> (#-1), event #0, src 127.0.0.1:31092 |
855 | - buffer starts at 0 (including 0 out), 16334 free, |
856 | - len 50, wraps at 16336, error at position 33 |
857 | - H1 connection flags 0x00000000, H1 stream flags 0x00000810 |
858 | - H1 msg state MSG_HDR_NAME(17), H1 msg flags 0x00001410 |
859 | - H1 chunk len 0 bytes, H1 body len 0 bytes : |
860 | - |
861 | - 00000 GET / HTTP/1.1\r\n |
862 | - 00016 Host: localhost\r\n |
863 | - 00033 :empty header\r\n |
864 | - 00048 \r\n |
865 | - |
866 | -I want to address sincere and warm thanks for their great work to the |
867 | -team composed of the following security researchers who found the issue |
868 | -together and reported it: Bahruz Jabiyev, Anthony Gavazzi, and Engin |
869 | -Kirda from Northeastern University, Kaan Onarlioglu from Akamai |
870 | -Technologies, Adi Peleg and Harvey Tuch from Google. And kudos to Amaury |
871 | -Denoyelle from HAProxy Technologies for spotting that the HPACK and |
872 | -QPACK decoders would let this pass despite the comment explicitly |
873 | -saying otherwise. |
874 | - |
875 | -This fix must be backported as far as 2.0. The QPACK changes can be |
876 | -dropped before 2.6. In 2.0 there is also the equivalent code for legacy |
877 | -mode, which doesn't suffer from the list truncation, but it would better |
878 | -be fixed regardless. |
879 | ---- |
880 | - src/h1.c | 4 ++++ |
881 | - src/hpack-dec.c | 9 +++++++++ |
882 | - src/qpack-dec.c | 9 +++++++++ |
883 | - 3 files changed, 22 insertions(+) |
884 | - |
885 | ---- a/src/h1.c |
886 | -+++ b/src/h1.c |
887 | -@@ -706,6 +706,10 @@ int h1_headers_to_hdr_list(char *start, |
888 | - |
889 | - if (likely(*ptr == ':')) { |
890 | - col = ptr - start; |
891 | -+ if (col <= sol) { |
892 | -+ state = H1_MSG_HDR_NAME; |
893 | -+ goto http_msg_invalid; |
894 | -+ } |
895 | - EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_hdr_l1_sp, http_msg_ood, state, H1_MSG_HDR_L1_SP); |
896 | - } |
897 | - |
898 | ---- a/src/hpack-dec.c |
899 | -+++ b/src/hpack-dec.c |
900 | -@@ -419,6 +419,15 @@ int hpack_decode_frame(struct hpack_dht |
901 | - /* <name> and <value> are correctly filled here */ |
902 | - } |
903 | - |
904 | -+ /* We must not accept empty header names (forbidden by the spec and used |
905 | -+ * as a list termination). |
906 | -+ */ |
907 | -+ if (!name.len) { |
908 | -+ hpack_debug_printf("##ERR@%d##\n", __LINE__); |
909 | -+ ret = -HPACK_ERR_INVALID_ARGUMENT; |
910 | -+ goto leave; |
911 | -+ } |
912 | -+ |
913 | - /* here's what we have here : |
914 | - * - name.len > 0 |
915 | - * - value is filled with either const data or data allocated from tmp |
916 | diff --git a/debian/patches/haproxy.service-start-after-syslog.patch b/debian/patches/haproxy.service-start-after-syslog.patch |
917 | index 14577bd..af62681 100644 |
918 | --- a/debian/patches/haproxy.service-start-after-syslog.patch |
919 | +++ b/debian/patches/haproxy.service-start-after-syslog.patch |
920 | @@ -13,8 +13,6 @@ Last-Update: 2017-12-01 |
921 | admin/systemd/haproxy.service.in | 2 +- |
922 | 1 file changed, 1 insertion(+), 1 deletion(-) |
923 | |
924 | -diff --git a/admin/systemd/haproxy.service.in b/admin/systemd/haproxy.service.in |
925 | -index 74e66e3..243acf2 100644 |
926 | --- a/admin/systemd/haproxy.service.in |
927 | +++ b/admin/systemd/haproxy.service.in |
928 | @@ -1,6 +1,6 @@ |
929 | diff --git a/debian/patches/reproducible.patch b/debian/patches/reproducible.patch |
930 | index bbc95b8..e499a79 100644 |
931 | --- a/debian/patches/reproducible.patch |
932 | +++ b/debian/patches/reproducible.patch |
933 | @@ -1,8 +1,6 @@ |
934 | -diff --git a/Makefile b/Makefile |
935 | -index 566bdb26a3e7..8603dea25c21 100644 |
936 | --- a/Makefile |
937 | +++ b/Makefile |
938 | -@@ -975,7 +975,7 @@ src/haproxy.o: src/haproxy.c $(DEP) |
939 | +@@ -995,7 +995,7 @@ |
940 | -DBUILD_ARCH='"$(strip $(ARCH))"' \ |
941 | -DBUILD_CPU='"$(strip $(CPU))"' \ |
942 | -DBUILD_CC='"$(strip $(CC))"' \ |
943 | diff --git a/debian/patches/series b/debian/patches/series |
944 | index 25260a8..276b0d5 100644 |
945 | --- a/debian/patches/series |
946 | +++ b/debian/patches/series |
947 | @@ -4,6 +4,3 @@ haproxy.service-add-documentation.patch |
948 | # applied during the build process: |
949 | # debianize-dconv.patch |
950 | reproducible.patch |
951 | -CVE-2023-0056.patch |
952 | -CVE-2023-25725.patch |
953 | -CVE-2023-0836.patch |
954 | diff --git a/debian/tests/control b/debian/tests/control |
955 | index 70649e3..ccc2b53 100644 |
956 | --- a/debian/tests/control |
957 | +++ b/debian/tests/control |
958 | @@ -5,3 +5,11 @@ Restrictions: needs-root |
959 | Tests: proxy-localhost |
960 | Depends: haproxy, wget, apache2 |
961 | Restrictions: needs-root, allow-stderr, isolation-container |
962 | + |
963 | +Tests: proxy-ssl-termination |
964 | +Depends: haproxy, wget, apache2, gnutls-bin, ssl-cert |
965 | +Restrictions: needs-root, allow-stderr, isolation-container |
966 | + |
967 | +Tests: proxy-ssl-pass-through |
968 | +Depends: haproxy, wget, apache2, gnutls-bin, ssl-cert |
969 | +Restrictions: needs-root, allow-stderr, isolation-container |
970 | diff --git a/debian/tests/proxy-localhost b/debian/tests/proxy-localhost |
971 | index 8f33d4f..0736985 100644 |
972 | --- a/debian/tests/proxy-localhost |
973 | +++ b/debian/tests/proxy-localhost |
974 | @@ -2,6 +2,9 @@ |
975 | |
976 | set -eux |
977 | |
978 | +WDIR=$(dirname "$0") |
979 | +. "${WDIR}/utils" |
980 | + |
981 | cat > /etc/haproxy/haproxy.cfg <<EOF |
982 | global |
983 | chroot /var/lib/haproxy |
984 | @@ -36,14 +39,6 @@ EOF |
985 | service haproxy restart |
986 | sleep 2 # Apache 2 could be still starting... See #976997. |
987 | |
988 | -# index.html is shipped with apache2 |
989 | -# Download it via haproxy and compare |
990 | -if wget -t1 http://localhost:8080 -O- | cmp /var/www/html/index.html -; then |
991 | - echo "OK: index.html downloaded via haproxy matches the source file." |
992 | -else |
993 | - echo "FAIL: downloaded index.html via haproxy is different from the" |
994 | - echo " file delivered by apache." |
995 | - exit 1 |
996 | -fi |
997 | +check_index_file "http://localhost:8080" |
998 | |
999 | exit 0 |
1000 | diff --git a/debian/tests/proxy-ssl-pass-through b/debian/tests/proxy-ssl-pass-through |
1001 | new file mode 100644 |
1002 | index 0000000..aa0bd2c |
1003 | --- /dev/null |
1004 | +++ b/debian/tests/proxy-ssl-pass-through |
1005 | @@ -0,0 +1,59 @@ |
1006 | +#!/bin/sh |
1007 | + |
1008 | +set -eux |
1009 | + |
1010 | +WDIR=$(dirname "$0") |
1011 | +. "${WDIR}/utils" |
1012 | + |
1013 | +CERT_DIR=/etc/ssl/localhost |
1014 | +APACHE2_CONFIG=/etc/apache2/sites-available/default-ssl.conf |
1015 | + |
1016 | +create_ca |
1017 | +create_selfsigned_cert ${CERT_DIR} |
1018 | + |
1019 | +# Use the self-signed certificate in apache2 config |
1020 | +sed -i "s#/etc/ssl/certs/ssl-cert-snakeoil.pem#${CERT_DIR}/localhost_cert.pem#" ${APACHE2_CONFIG} |
1021 | +sed -i "s#/etc/ssl/private/ssl-cert-snakeoil.key#${CERT_DIR}/localhost_key.pem#" ${APACHE2_CONFIG} |
1022 | + |
1023 | +cat > /etc/haproxy/haproxy.cfg <<EOF |
1024 | +global |
1025 | + chroot /var/lib/haproxy |
1026 | + user haproxy |
1027 | + group haproxy |
1028 | + daemon |
1029 | + maxconn 4096 |
1030 | + |
1031 | +defaults |
1032 | + log global |
1033 | + option dontlognull |
1034 | + option redispatch |
1035 | + retries 3 |
1036 | + timeout client 50s |
1037 | + timeout connect 10s |
1038 | + timeout http-request 5s |
1039 | + timeout server 50s |
1040 | + maxconn 4096 |
1041 | + |
1042 | +frontend test-front |
1043 | + bind *:4433 |
1044 | + mode tcp |
1045 | + option tcplog |
1046 | + default_backend test-back |
1047 | + |
1048 | +backend test-back |
1049 | + mode tcp |
1050 | + stick store-request src |
1051 | + stick-table type ip size 256k expire 30m |
1052 | + option ssl-hello-chk |
1053 | + server test-1 localhost:443 check |
1054 | +EOF |
1055 | + |
1056 | +systemctl restart haproxy |
1057 | +a2enmod ssl |
1058 | +a2ensite default-ssl |
1059 | +systemctl restart apache2 |
1060 | +sleep 5 # Apache 2 could be still starting... See #976997. It needs some extra seconds because of SSL |
1061 | + |
1062 | +check_index_file "https://localhost:4433" |
1063 | + |
1064 | +exit 0 |
1065 | diff --git a/debian/tests/proxy-ssl-termination b/debian/tests/proxy-ssl-termination |
1066 | new file mode 100644 |
1067 | index 0000000..6cc1bcc |
1068 | --- /dev/null |
1069 | +++ b/debian/tests/proxy-ssl-termination |
1070 | @@ -0,0 +1,48 @@ |
1071 | +#!/bin/sh |
1072 | + |
1073 | +set -eux |
1074 | + |
1075 | +WDIR=$(dirname "$0") |
1076 | +. "${WDIR}/utils" |
1077 | + |
1078 | +CERT_DIR=/etc/ssl/localhost |
1079 | +create_ca |
1080 | +create_selfsigned_cert ${CERT_DIR} |
1081 | + |
1082 | +cat > /etc/haproxy/haproxy.cfg <<EOF |
1083 | +global |
1084 | + chroot /var/lib/haproxy |
1085 | + user haproxy |
1086 | + group haproxy |
1087 | + daemon |
1088 | + maxconn 4096 |
1089 | + ssl-default-bind-options ssl-min-ver SSLv3 |
1090 | + |
1091 | +defaults |
1092 | + log global |
1093 | + option dontlognull |
1094 | + option redispatch |
1095 | + retries 3 |
1096 | + timeout client 50s |
1097 | + timeout connect 10s |
1098 | + timeout http-request 5s |
1099 | + timeout server 50s |
1100 | + maxconn 4096 |
1101 | + |
1102 | +frontend test-front |
1103 | + bind *:443 ssl crt ${CERT_DIR}/localhost.pem |
1104 | + default_backend test-back |
1105 | + |
1106 | +backend test-back |
1107 | + mode http |
1108 | + stick store-request src |
1109 | + stick-table type ip size 256k expire 30m |
1110 | + server test-1 localhost:80 check |
1111 | +EOF |
1112 | + |
1113 | +systemctl restart haproxy |
1114 | +sleep 2 # Apache 2 could be still starting... See #976997. |
1115 | + |
1116 | +check_index_file "https://localhost" |
1117 | + |
1118 | +exit 0 |
1119 | diff --git a/debian/tests/utils b/debian/tests/utils |
1120 | new file mode 100644 |
1121 | index 0000000..df11b55 |
1122 | --- /dev/null |
1123 | +++ b/debian/tests/utils |
1124 | @@ -0,0 +1,58 @@ |
1125 | + |
1126 | +create_ca() { |
1127 | + certtool --generate-privkey --bits 4096 --outfile /etc/ssl/private/mycakey.pem |
1128 | + |
1129 | + cat <<EOF > /etc/ssl/ca.info |
1130 | +cn = Example Company |
1131 | +ca |
1132 | +cert_signing_key |
1133 | +expiration_days = 3650 |
1134 | +EOF |
1135 | + |
1136 | + certtool --generate-self-signed \ |
1137 | + --load-privkey /etc/ssl/private/mycakey.pem \ |
1138 | + --template /etc/ssl/ca.info \ |
1139 | + --outfile /usr/local/share/ca-certificates/mycacert.crt |
1140 | + |
1141 | + update-ca-certificates |
1142 | +} |
1143 | + |
1144 | +create_selfsigned_cert() { |
1145 | + dir="$1" |
1146 | + mkdir -p "${dir}" |
1147 | + |
1148 | + certtool --generate-privkey --bits 2048 --outfile "${dir}/localhost_key.pem" |
1149 | + |
1150 | + cat <<EOF > "${dir}/localhost.info" |
1151 | +organization = Example Company |
1152 | +cn = localhost |
1153 | +tls_www_server |
1154 | +encryption_key |
1155 | +signing_key |
1156 | +expiration_days = 365 |
1157 | +EOF |
1158 | + |
1159 | + certtool --generate-certificate \ |
1160 | + --load-privkey "${dir}/localhost_key.pem" \ |
1161 | + --load-ca-certificate /etc/ssl/certs/mycacert.pem \ |
1162 | + --load-ca-privkey /etc/ssl/private/mycakey.pem \ |
1163 | + --template "${dir}/localhost.info" \ |
1164 | + --outfile "${dir}/localhost_cert.pem" |
1165 | + |
1166 | + cat "${dir}/localhost_cert.pem" "${dir}/localhost_key.pem" | tee "${dir}/localhost.pem" |
1167 | + chgrp haproxy "${dir}/localhost_key.pem" "${dir}/localhost.pem" |
1168 | + chmod 0640 "${dir}/localhost_key.pem" "${dir}/localhost.pem" |
1169 | +} |
1170 | + |
1171 | +check_index_file() { |
1172 | + haproxy_url="$1" |
1173 | + # index.html is shipped with apache2 |
1174 | + # Download it via haproxy and compare |
1175 | + if wget -t1 "${haproxy_url}" -O- | cmp /var/www/html/index.html -; then |
1176 | + echo "OK: index.html downloaded via haproxy matches the source file." |
1177 | + else |
1178 | + echo "FAIL: downloaded index.html via haproxy is different from the" |
1179 | + echo " file delivered by apache." |
1180 | + exit 1 |
1181 | + fi |
1182 | +} |
1183 | diff --git a/doc/configuration.txt b/doc/configuration.txt |
1184 | index 5d4c052..0c23dd1 100644 |
1185 | --- a/doc/configuration.txt |
1186 | +++ b/doc/configuration.txt |
1187 | @@ -3,7 +3,7 @@ |
1188 | Configuration Manual |
1189 | ---------------------- |
1190 | version 2.4 |
1191 | - 2022/07/27 |
1192 | + 2023/02/14 |
1193 | |
1194 | |
1195 | This document covers the configuration language as implemented in the version |
1196 | @@ -965,32 +965,36 @@ of them have command-line equivalents. |
1197 | The following keywords are supported in the "global" section : |
1198 | |
1199 | * Process management and security |
1200 | + - 51degrees-cache-size |
1201 | + - 51degrees-data-file |
1202 | + - 51degrees-property-name-list |
1203 | + - 51degrees-property-separator |
1204 | - ca-base |
1205 | - chroot |
1206 | - - crt-base |
1207 | - cpu-map |
1208 | + - crt-base |
1209 | - daemon |
1210 | - default-path |
1211 | - description |
1212 | - deviceatlas-json-file |
1213 | - deviceatlas-log-level |
1214 | - - deviceatlas-separator |
1215 | - deviceatlas-properties-cookie |
1216 | + - deviceatlas-separator |
1217 | - expose-experimental-directives |
1218 | - external-check |
1219 | - gid |
1220 | - group |
1221 | - - hard-stop-after |
1222 | - h1-case-adjust |
1223 | - h1-case-adjust-file |
1224 | + - h2-workaround-bogus-websocket-clients |
1225 | + - hard-stop-after |
1226 | - insecure-fork-wanted |
1227 | - insecure-setuid-wanted |
1228 | - issuers-chain-path |
1229 | - - h2-workaround-bogus-websocket-clients |
1230 | - localpeer |
1231 | - log |
1232 | - - log-tag |
1233 | - log-send-hostname |
1234 | + - log-tag |
1235 | - lua-load |
1236 | - lua-load-per-thread |
1237 | - lua-prepend-path |
1238 | @@ -1003,13 +1007,9 @@ The following keywords are supported in the "global" section : |
1239 | - pp2-never-send-local |
1240 | - presetenv |
1241 | - resetenv |
1242 | - - uid |
1243 | - - ulimit-n |
1244 | - - user |
1245 | - set-dumpable |
1246 | - set-var |
1247 | - setenv |
1248 | - - stats |
1249 | - ssl-default-bind-ciphers |
1250 | - ssl-default-bind-ciphersuites |
1251 | - ssl-default-bind-curves |
1252 | @@ -1020,25 +1020,25 @@ The following keywords are supported in the "global" section : |
1253 | - ssl-dh-param-file |
1254 | - ssl-server-verify |
1255 | - ssl-skip-self-issued-ca |
1256 | + - stats |
1257 | + - strict-limits |
1258 | + - uid |
1259 | + - ulimit-n |
1260 | - unix-bind |
1261 | - unsetenv |
1262 | - - 51degrees-data-file |
1263 | - - 51degrees-property-name-list |
1264 | - - 51degrees-property-separator |
1265 | - - 51degrees-cache-size |
1266 | + - user |
1267 | + - wurfl-cache-size |
1268 | - wurfl-data-file |
1269 | - wurfl-information-list |
1270 | - wurfl-information-list-separator |
1271 | - - wurfl-cache-size |
1272 | - - strict-limits |
1273 | |
1274 | * Performance tuning |
1275 | - busy-polling |
1276 | - max-spread-checks |
1277 | + - maxcompcpuusage |
1278 | + - maxcomprate |
1279 | - maxconn |
1280 | - maxconnrate |
1281 | - - maxcomprate |
1282 | - - maxcompcpuusage |
1283 | - maxpipes |
1284 | - maxsessrate |
1285 | - maxsslconn |
1286 | @@ -1046,16 +1046,16 @@ The following keywords are supported in the "global" section : |
1287 | - maxzlibmem |
1288 | - no-memory-trimming |
1289 | - noepoll |
1290 | - - nokqueue |
1291 | - noevports |
1292 | - - nopoll |
1293 | - - nosplice |
1294 | - nogetaddrinfo |
1295 | + - nokqueue |
1296 | + - nopoll |
1297 | - noreuseport |
1298 | + - nosplice |
1299 | - profiling.tasks |
1300 | - - spread-checks |
1301 | - server-state-base |
1302 | - server-state-file |
1303 | + - spread-checks |
1304 | - ssl-engine |
1305 | - ssl-mode-async |
1306 | - tune.buffers.limit |
1307 | @@ -1074,9 +1074,9 @@ The following keywords are supported in the "global" section : |
1308 | - tune.idletimer |
1309 | - tune.lua.forced-yield |
1310 | - tune.lua.maxmem |
1311 | + - tune.lua.service-timeout |
1312 | - tune.lua.session-timeout |
1313 | - tune.lua.task-timeout |
1314 | - - tune.lua.service-timeout |
1315 | - tune.maxaccept |
1316 | - tune.maxpollevents |
1317 | - tune.maxrewrite |
1318 | @@ -1092,13 +1092,13 @@ The following keywords are supported in the "global" section : |
1319 | - tune.sndbuf.client |
1320 | - tune.sndbuf.server |
1321 | - tune.ssl.cachesize |
1322 | + - tune.ssl.capture-cipherlist-size |
1323 | + - tune.ssl.default-dh-param |
1324 | + - tune.ssl.force-private-cache |
1325 | - tune.ssl.keylog |
1326 | - tune.ssl.lifetime |
1327 | - - tune.ssl.force-private-cache |
1328 | - tune.ssl.maxrecord |
1329 | - - tune.ssl.default-dh-param |
1330 | - tune.ssl.ssl-ctx-cache-size |
1331 | - - tune.ssl.capture-cipherlist-size |
1332 | - tune.vars.global-max-size |
1333 | - tune.vars.proc-max-size |
1334 | - tune.vars.reqres-max-size |
1335 | @@ -1115,6 +1115,36 @@ The following keywords are supported in the "global" section : |
1336 | 3.1. Process management and security |
1337 | ------------------------------------ |
1338 | |
1339 | +51degrees-data-file <file path> |
1340 | + The path of the 51Degrees data file to provide device detection services. The |
1341 | + file should be unzipped and accessible by HAProxy with relevant permissions. |
1342 | + |
1343 | + Please note that this option is only available when HAProxy has been |
1344 | + compiled with USE_51DEGREES. |
1345 | + |
1346 | +51degrees-property-name-list [<string> ...] |
1347 | + A list of 51Degrees property names to be load from the dataset. A full list |
1348 | + of names is available on the 51Degrees website: |
1349 | + https://51degrees.com/resources/property-dictionary |
1350 | + |
1351 | + Please note that this option is only available when HAProxy has been |
1352 | + compiled with USE_51DEGREES. |
1353 | + |
1354 | +51degrees-property-separator <char> |
1355 | + A char that will be appended to every property value in a response header |
1356 | + containing 51Degrees results. If not set that will be set as ','. |
1357 | + |
1358 | + Please note that this option is only available when HAProxy has been |
1359 | + compiled with USE_51DEGREES. |
1360 | + |
1361 | +51degrees-cache-size <number> |
1362 | + Sets the size of the 51Degrees converter cache to <number> entries. This |
1363 | + is an LRU cache which reminds previous device detections and their results. |
1364 | + By default, this cache is disabled. |
1365 | + |
1366 | + Please note that this option is only available when HAProxy has been |
1367 | + compiled with USE_51DEGREES. |
1368 | + |
1369 | ca-base <dir> |
1370 | Assigns a default directory to fetch SSL CA certificates and CRLs from when a |
1371 | relative path is used with "ca-file", "ca-verify-file" or "crl-file" |
1372 | @@ -1267,6 +1297,13 @@ default-path { current | config | parent | origin <path> } |
1373 | paths. A robust approach could consist in prefixing all files names with |
1374 | their respective site name, or in doing so at the directory level. |
1375 | |
1376 | +description <text> |
1377 | + Add a text that describes the instance. |
1378 | + |
1379 | + Please note that it is required to escape certain characters (# for example) |
1380 | + and this text is inserted into a html page so you should avoid using |
1381 | + "<" and ">" characters. |
1382 | + |
1383 | deviceatlas-json-file <path> |
1384 | Sets the path of the DeviceAtlas JSON data file to be loaded by the API. |
1385 | The path must be a valid JSON data file and accessible by HAProxy process. |
1386 | @@ -1275,15 +1312,15 @@ deviceatlas-log-level <value> |
1387 | Sets the level of information returned by the API. This directive is |
1388 | optional and set to 0 by default if not set. |
1389 | |
1390 | -deviceatlas-separator <char> |
1391 | - Sets the character separator for the API properties results. This directive |
1392 | - is optional and set to | by default if not set. |
1393 | - |
1394 | deviceatlas-properties-cookie <name> |
1395 | Sets the client cookie's name used for the detection if the DeviceAtlas |
1396 | Client-side component was used during the request. This directive is optional |
1397 | and set to DAPROPS by default if not set. |
1398 | |
1399 | +deviceatlas-separator <char> |
1400 | + Sets the character separator for the API properties results. This directive |
1401 | + is optional and set to | by default if not set. |
1402 | + |
1403 | expose-experimental-directives |
1404 | This statement must appear before using directives tagged as experimental or |
1405 | the config file will be rejected. |
1406 | @@ -1309,22 +1346,6 @@ group <group name> |
1407 | Similar to "gid" but uses the GID of group name <group name> from /etc/group. |
1408 | See also "gid" and "user". |
1409 | |
1410 | -hard-stop-after <time> |
1411 | - Defines the maximum time allowed to perform a clean soft-stop. |
1412 | - |
1413 | - Arguments : |
1414 | - <time> is the maximum time (by default in milliseconds) for which the |
1415 | - instance will remain alive when a soft-stop is received via the |
1416 | - SIGUSR1 signal. |
1417 | - |
1418 | - This may be used to ensure that the instance will quit even if connections |
1419 | - remain opened during a soft-stop (for example with long timeouts for a proxy |
1420 | - in tcp mode). It applies both in TCP and HTTP mode. |
1421 | - |
1422 | - Example: |
1423 | - global |
1424 | - hard-stop-after 30s |
1425 | - |
1426 | h1-case-adjust <from> <to> |
1427 | Defines the case adjustment to apply, when enabled, to the header name |
1428 | <from>, to change it to <to> before sending it to HTTP/1 clients or |
1429 | @@ -1374,6 +1395,33 @@ h1-case-adjust-file <hdrs-file> |
1430 | See "h1-case-adjust", "option h1-case-adjust-bogus-client" and |
1431 | "option h1-case-adjust-bogus-server". |
1432 | |
1433 | +h2-workaround-bogus-websocket-clients |
1434 | + This disables the announcement of the support for h2 websockets to clients. |
1435 | + This can be use to overcome clients which have issues when implementing the |
1436 | + relatively fresh RFC8441, such as Firefox 88. To allow clients to |
1437 | + automatically downgrade to http/1.1 for the websocket tunnel, specify h2 |
1438 | + support on the bind line using "alpn" without an explicit "proto" keyword. If |
1439 | + this statement was previously activated, this can be disabled by prefixing |
1440 | + the keyword with "no'. |
1441 | + |
1442 | +hard-stop-after <time> |
1443 | + Defines the maximum time allowed to perform a clean soft-stop. |
1444 | + |
1445 | + Arguments : |
1446 | + <time> is the maximum time (by default in milliseconds) for which the |
1447 | + instance will remain alive when a soft-stop is received via the |
1448 | + SIGUSR1 signal. |
1449 | + |
1450 | + This may be used to ensure that the instance will quit even if connections |
1451 | + remain opened during a soft-stop (for example with long timeouts for a proxy |
1452 | + in tcp mode). It applies both in TCP and HTTP mode. |
1453 | + |
1454 | + Example: |
1455 | + global |
1456 | + hard-stop-after 30s |
1457 | + |
1458 | + See also: grace |
1459 | + |
1460 | insecure-fork-wanted |
1461 | By default HAProxy tries hard to prevent any thread and process creation |
1462 | after it starts. Doing so is particularly important when using Lua files of |
1463 | @@ -1421,15 +1469,6 @@ issuers-chain-path <dir> |
1464 | "issuers-chain-path" directory. All other certificates with the same issuer |
1465 | will share the chain in memory. |
1466 | |
1467 | -h2-workaround-bogus-websocket-clients |
1468 | - This disables the announcement of the support for h2 websockets to clients. |
1469 | - This can be use to overcome clients which have issues when implementing the |
1470 | - relatively fresh RFC8441, such as Firefox 88. To allow clients to |
1471 | - automatically downgrade to http/1.1 for the websocket tunnel, specify h2 |
1472 | - support on the bind line using "alpn" without an explicit "proto" keyword. If |
1473 | - this statement was previously activated, this can be disabled by prefixing |
1474 | - the keyword with "no'. |
1475 | - |
1476 | localpeer <name> |
1477 | Sets the local instance's peer name. It will be ignored if the "-L" |
1478 | command line argument is specified or if used after "peers" section |
1479 | @@ -1762,6 +1801,26 @@ server-state-file <file> |
1480 | configuration. See also "server-state-base" and "show servers state", |
1481 | "load-server-state-from-file" and "server-state-file-name" |
1482 | |
1483 | +set-dumpable |
1484 | + This option is better left disabled by default and enabled only upon a |
1485 | + developer's request. If it has been enabled, it may still be forcibly |
1486 | + disabled by prefixing it with the "no" keyword. It has no impact on |
1487 | + performance nor stability but will try hard to re-enable core dumps that were |
1488 | + possibly disabled by file size limitations (ulimit -f), core size limitations |
1489 | + (ulimit -c), or "dumpability" of a process after changing its UID/GID (such |
1490 | + as /proc/sys/fs/suid_dumpable on Linux). Core dumps might still be limited by |
1491 | + the current directory's permissions (check what directory the file is started |
1492 | + from), the chroot directory's permission (it may be needed to temporarily |
1493 | + disable the chroot directive or to move it to a dedicated writable location), |
1494 | + or any other system-specific constraint. For example, some Linux flavours are |
1495 | + notorious for replacing the default core file with a path to an executable |
1496 | + not even installed on the system (check /proc/sys/kernel/core_pattern). Often, |
1497 | + simply writing "core", "core.%p" or "/var/log/core/core.%p" addresses the |
1498 | + issue. When trying to enable this option waiting for a rare issue to |
1499 | + re-appear, it's often a good idea to first try to obtain such a dump by |
1500 | + issuing, for example, "kill -11" to the "haproxy" process and verify that it |
1501 | + leaves a core where expected when dying. |
1502 | + |
1503 | set-var <var-name> <expr> |
1504 | Sets the process-wide variable '<var-name>' to the result of the evaluation |
1505 | of the sample expression <expr>. The variable '<var-name>' may only be a |
1506 | @@ -1785,26 +1844,6 @@ setenv <name> <value> |
1507 | the configuration file sees the new value. See also "presetenv", "resetenv", |
1508 | and "unsetenv". |
1509 | |
1510 | -set-dumpable |
1511 | - This option is better left disabled by default and enabled only upon a |
1512 | - developer's request. If it has been enabled, it may still be forcibly |
1513 | - disabled by prefixing it with the "no" keyword. It has no impact on |
1514 | - performance nor stability but will try hard to re-enable core dumps that were |
1515 | - possibly disabled by file size limitations (ulimit -f), core size limitations |
1516 | - (ulimit -c), or "dumpability" of a process after changing its UID/GID (such |
1517 | - as /proc/sys/fs/suid_dumpable on Linux). Core dumps might still be limited by |
1518 | - the current directory's permissions (check what directory the file is started |
1519 | - from), the chroot directory's permission (it may be needed to temporarily |
1520 | - disable the chroot directive or to move it to a dedicated writable location), |
1521 | - or any other system-specific constraint. For example, some Linux flavours are |
1522 | - notorious for replacing the default core file with a path to an executable |
1523 | - not even installed on the system (check /proc/sys/kernel/core_pattern). Often, |
1524 | - simply writing "core", "core.%p" or "/var/log/core/core.%p" addresses the |
1525 | - issue. When trying to enable this option waiting for a rare issue to |
1526 | - re-appear, it's often a good idea to first try to obtain such a dump by |
1527 | - issuing, for example, "kill -11" to the "haproxy" process and verify that it |
1528 | - leaves a core where expected when dying. |
1529 | - |
1530 | ssl-default-bind-ciphers <ciphers> |
1531 | This setting is only available when support for OpenSSL was built in. It sets |
1532 | the default string describing the list of cipher algorithms ("cipher suite") |
1533 | @@ -1995,6 +2034,10 @@ ssl-skip-self-issued-ca |
1534 | certificates. It's useless for BoringSSL, .issuer is ignored because ocsp |
1535 | bits does not need it. Requires at least OpenSSL 1.0.2. |
1536 | |
1537 | +stats maxconn <connections> |
1538 | + By default, the stats socket is limited to 10 concurrent connections. It is |
1539 | + possible to change this value with "stats maxconn". |
1540 | + |
1541 | stats socket [<address:port>|<path>] [param*] |
1542 | Binds a UNIX socket to <path> or a TCPv4/v6 address to <address:port>. |
1543 | Connections to this socket will return various statistics outputs and even |
1544 | @@ -2011,9 +2054,12 @@ stats timeout <timeout, in milliseconds> |
1545 | to change this value with "stats timeout". The value must be passed in |
1546 | milliseconds, or be suffixed by a time unit among { us, ms, s, m, h, d }. |
1547 | |
1548 | -stats maxconn <connections> |
1549 | - By default, the stats socket is limited to 10 concurrent connections. It is |
1550 | - possible to change this value with "stats maxconn". |
1551 | +strict-limits |
1552 | + Makes process fail at startup when a setrlimit fails. HAProxy tries to set the |
1553 | + best setrlimit according to what has been calculated. If it fails, it will |
1554 | + emit a warning. This option is here to guarantee an explicit failure of |
1555 | + HAProxy when those limits fail. It is enabled by default. It may still be |
1556 | + forcibly disabled by prefixing it with the "no" keyword. |
1557 | |
1558 | uid <number> |
1559 | Changes the process's user ID to <number>. It is recommended that the user ID |
1560 | @@ -2061,42 +2107,14 @@ node <name> |
1561 | nodes, it becomes easy to immediately spot what server is handling the |
1562 | traffic. |
1563 | |
1564 | -description <text> |
1565 | - Add a text that describes the instance. |
1566 | - |
1567 | - Please note that it is required to escape certain characters (# for example) |
1568 | - and this text is inserted into a html page so you should avoid using |
1569 | - "<" and ">" characters. |
1570 | - |
1571 | -51degrees-data-file <file path> |
1572 | - The path of the 51Degrees data file to provide device detection services. The |
1573 | - file should be unzipped and accessible by HAProxy with relevant permissions. |
1574 | - |
1575 | - Please note that this option is only available when HAProxy has been |
1576 | - compiled with USE_51DEGREES. |
1577 | - |
1578 | -51degrees-property-name-list [<string> ...] |
1579 | - A list of 51Degrees property names to be load from the dataset. A full list |
1580 | - of names is available on the 51Degrees website: |
1581 | - https://51degrees.com/resources/property-dictionary |
1582 | - |
1583 | - Please note that this option is only available when HAProxy has been |
1584 | - compiled with USE_51DEGREES. |
1585 | - |
1586 | -51degrees-property-separator <char> |
1587 | - A char that will be appended to every property value in a response header |
1588 | - containing 51Degrees results. If not set that will be set as ','. |
1589 | - |
1590 | - Please note that this option is only available when HAProxy has been |
1591 | - compiled with USE_51DEGREES. |
1592 | - |
1593 | -51degrees-cache-size <number> |
1594 | - Sets the size of the 51Degrees converter cache to <number> entries. This |
1595 | - is an LRU cache which reminds previous device detections and their results. |
1596 | - By default, this cache is disabled. |
1597 | +wurfl-cache-size <size> |
1598 | + Sets the WURFL Useragent cache size. For faster lookups, already processed user |
1599 | + agents are kept in a LRU cache : |
1600 | + - "0" : no cache is used. |
1601 | + - <size> : size of lru cache in elements. |
1602 | |
1603 | - Please note that this option is only available when HAProxy has been |
1604 | - compiled with USE_51DEGREES. |
1605 | + Please note that this option is only available when HAProxy has been compiled |
1606 | + with USE_WURFL=1. |
1607 | |
1608 | wurfl-data-file <file path> |
1609 | The path of the WURFL data file to provide device detection services. The |
1610 | @@ -2152,22 +2170,6 @@ wurfl-patch-file [<file path>] |
1611 | Please note that this option is only available when HAProxy has been compiled |
1612 | with USE_WURFL=1. |
1613 | |
1614 | -wurfl-cache-size <size> |
1615 | - Sets the WURFL Useragent cache size. For faster lookups, already processed user |
1616 | - agents are kept in a LRU cache : |
1617 | - - "0" : no cache is used. |
1618 | - - <size> : size of lru cache in elements. |
1619 | - |
1620 | - Please note that this option is only available when HAProxy has been compiled |
1621 | - with USE_WURFL=1. |
1622 | - |
1623 | -strict-limits |
1624 | - Makes process fail at startup when a setrlimit fails. HAProxy tries to set the |
1625 | - best setrlimit according to what has been calculated. If it fails, it will |
1626 | - emit a warning. This option is here to guarantee an explicit failure of |
1627 | - HAProxy when those limits fail. It is enabled by default. It may still be |
1628 | - forcibly disabled by prefixing it with the "no" keyword. |
1629 | - |
1630 | 3.2. Performance tuning |
1631 | ----------------------- |
1632 | |
1633 | @@ -2204,6 +2206,24 @@ max-spread-checks <delay in milliseconds> |
1634 | even if the servers' check intervals are larger. When servers run with |
1635 | shorter intervals, their intervals will be respected though. |
1636 | |
1637 | +maxcompcpuusage <number> |
1638 | + Sets the maximum CPU usage HAProxy can reach before stopping the compression |
1639 | + for new requests or decreasing the compression level of current requests. |
1640 | + It works like 'maxcomprate' but measures CPU usage instead of incoming data |
1641 | + bandwidth. The value is expressed in percent of the CPU used by HAProxy. A |
1642 | + value of 100 disable the limit. The default value is 100. Setting a lower |
1643 | + value will prevent the compression work from slowing the whole process down |
1644 | + and from introducing high latencies. |
1645 | + |
1646 | +maxcomprate <number> |
1647 | + Sets the maximum per-process input compression rate to <number> kilobytes |
1648 | + per second. For each session, if the maximum is reached, the compression |
1649 | + level will be decreased during the session. If the maximum is reached at the |
1650 | + beginning of a session, the session will not compress at all. If the maximum |
1651 | + is not reached, the compression level will be increased up to |
1652 | + tune.comp.maxlevel. A value of zero means there is no limit, this is the |
1653 | + default value. |
1654 | + |
1655 | maxconn <number> |
1656 | Sets the maximum per-process number of concurrent connections to <number>. It |
1657 | is equivalent to the command-line argument "-n". Proxies will stop accepting |
1658 | @@ -2229,25 +2249,6 @@ maxconnrate <number> |
1659 | value close to its expected share. Also, lowering tune.maxaccept can improve |
1660 | fairness. |
1661 | |
1662 | -maxcomprate <number> |
1663 | - Sets the maximum per-process input compression rate to <number> kilobytes |
1664 | - per second. For each session, if the maximum is reached, the compression |
1665 | - level will be decreased during the session. If the maximum is reached at the |
1666 | - beginning of a session, the session will not compress at all. If the maximum |
1667 | - is not reached, the compression level will be increased up to |
1668 | - tune.comp.maxlevel. A value of zero means there is no limit, this is the |
1669 | - default value. |
1670 | - |
1671 | -maxcompcpuusage <number> |
1672 | - Sets the maximum CPU usage HAProxy can reach before stopping the compression |
1673 | - for new requests or decreasing the compression level of current requests. |
1674 | - It works like 'maxcomprate' but measures CPU usage instead of incoming data |
1675 | - bandwidth. The value is expressed in percent of the CPU used by HAProxy. In |
1676 | - case of multiple processes (nbproc > 1), each process manages its individual |
1677 | - usage. A value of 100 disable the limit. The default value is 100. Setting |
1678 | - a lower value will prevent the compression work from slowing the whole |
1679 | - process down and from introducing high latencies. |
1680 | - |
1681 | maxpipes <number> |
1682 | Sets the maximum per-process number of pipes to <number>. Currently, pipes |
1683 | are only used by kernel-based tcp splicing. Since a pipe contains two file |
1684 | @@ -2323,17 +2324,21 @@ noepoll |
1685 | equivalent to the command-line argument "-de". The next polling system |
1686 | used will generally be "poll". See also "nopoll". |
1687 | |
1688 | -nokqueue |
1689 | - Disables the use of the "kqueue" event polling system on BSD. It is |
1690 | - equivalent to the command-line argument "-dk". The next polling system |
1691 | - used will generally be "poll". See also "nopoll". |
1692 | - |
1693 | noevports |
1694 | Disables the use of the event ports event polling system on SunOS systems |
1695 | derived from Solaris 10 and later. It is equivalent to the command-line |
1696 | argument "-dv". The next polling system used will generally be "poll". See |
1697 | also "nopoll". |
1698 | |
1699 | +nogetaddrinfo |
1700 | + Disables the use of getaddrinfo(3) for name resolving. It is equivalent to |
1701 | + the command line argument "-dG". Deprecated gethostbyname(3) will be used. |
1702 | + |
1703 | +nokqueue |
1704 | + Disables the use of the "kqueue" event polling system on BSD. It is |
1705 | + equivalent to the command-line argument "-dk". The next polling system |
1706 | + used will generally be "poll". See also "nopoll". |
1707 | + |
1708 | nopoll |
1709 | Disables the use of the "poll" event polling system. It is equivalent to the |
1710 | command-line argument "-dp". The next polling system used will be "select". |
1711 | @@ -2341,6 +2346,10 @@ nopoll |
1712 | platforms supported by HAProxy. See also "nokqueue", "noepoll" and |
1713 | "noevports". |
1714 | |
1715 | +noreuseport |
1716 | + Disables the use of SO_REUSEPORT - see socket(7). It is equivalent to the |
1717 | + command line argument "-dR". |
1718 | + |
1719 | nosplice |
1720 | Disables the use of kernel tcp splicing between sockets on Linux. It is |
1721 | equivalent to the command line argument "-dS". Data will then be copied |
1722 | @@ -2351,14 +2360,6 @@ nosplice |
1723 | case of doubt. See also "option splice-auto", "option splice-request" and |
1724 | "option splice-response". |
1725 | |
1726 | -nogetaddrinfo |
1727 | - Disables the use of getaddrinfo(3) for name resolving. It is equivalent to |
1728 | - the command line argument "-dG". Deprecated gethostbyname(3) will be used. |
1729 | - |
1730 | -noreuseport |
1731 | - Disables the use of SO_REUSEPORT - see socket(7). It is equivalent to the |
1732 | - command line argument "-dR". |
1733 | - |
1734 | profiling.memory { on | off } |
1735 | Enables ('on') or disables ('off') per-function memory profiling. This will |
1736 | keep usage statistics of malloc/calloc/realloc/free calls anywhere in the |
1737 | @@ -2604,18 +2605,18 @@ tune.lua.session-timeout <timeout> |
1738 | counts only the pure Lua runtime. If the Lua does a sleep, the sleep is |
1739 | not taken in account. The default timeout is 4s. |
1740 | |
1741 | -tune.lua.task-timeout <timeout> |
1742 | - Purpose is the same as "tune.lua.session-timeout", but this timeout is |
1743 | - dedicated to the tasks. By default, this timeout isn't set because a task may |
1744 | - remain alive during of the lifetime of HAProxy. For example, a task used to |
1745 | - check servers. |
1746 | - |
1747 | tune.lua.service-timeout <timeout> |
1748 | This is the execution timeout for the Lua services. This is useful for |
1749 | preventing infinite loops or spending too much time in Lua. This timeout |
1750 | counts only the pure Lua runtime. If the Lua does a sleep, the sleep is |
1751 | not taken in account. The default timeout is 4s. |
1752 | |
1753 | +tune.lua.task-timeout <timeout> |
1754 | + Purpose is the same as "tune.lua.session-timeout", but this timeout is |
1755 | + dedicated to the tasks. By default, this timeout isn't set because a task may |
1756 | + remain alive during of the lifetime of HAProxy. For example, a task used to |
1757 | + check servers. |
1758 | + |
1759 | tune.maxaccept <number> |
1760 | Sets the maximum number of consecutive connections a process may accept in a |
1761 | row before switching to other work. In single process mode, higher numbers |
1762 | @@ -2756,6 +2757,26 @@ tune.ssl.cachesize <number> |
1763 | pre-allocated upon startup and are shared between all processes if "nbproc" |
1764 | is greater than 1. Setting this value to 0 disables the SSL session cache. |
1765 | |
1766 | +tune.ssl.capture-cipherlist-size <number> |
1767 | + Sets the maximum size of the buffer used for capturing client hello cipher |
1768 | + list, extensions list, elliptic curves list and elliptic curve point |
1769 | + formats. If the value is 0 (default value) the capture is disabled, |
1770 | + otherwise a buffer is allocated for each SSL/TLS connection. |
1771 | + |
1772 | +tune.ssl.default-dh-param <number> |
1773 | + Sets the maximum size of the Diffie-Hellman parameters used for generating |
1774 | + the ephemeral/temporary Diffie-Hellman key in case of DHE key exchange. The |
1775 | + final size will try to match the size of the server's RSA (or DSA) key (e.g, |
1776 | + a 2048 bits temporary DH key for a 2048 bits RSA key), but will not exceed |
1777 | + this maximum value. Only 1024 or higher values are allowed. Higher values |
1778 | + will increase the CPU load, and values greater than 1024 bits are not |
1779 | + supported by Java 7 and earlier clients. This value is not used if static |
1780 | + Diffie-Hellman parameters are supplied either directly in the certificate |
1781 | + file or by using the ssl-dh-param-file parameter. |
1782 | + If there is neither a default-dh-param nor a ssl-dh-param-file defined, and |
1783 | + if the server's PEM file of a given frontend does not specify its own DH |
1784 | + parameters, then DHE ciphers will be unavailable for this frontend. |
1785 | + |
1786 | tune.ssl.force-private-cache |
1787 | This option disables SSL session cache sharing between all processes. It |
1788 | should normally not be used since it will force many renegotiations due to |
1789 | @@ -2824,28 +2845,12 @@ tune.ssl.maxrecord <number> |
1790 | best value. HAProxy will automatically switch to this setting after an idle |
1791 | stream has been detected (see tune.idletimer above). |
1792 | |
1793 | -tune.ssl.default-dh-param <number> |
1794 | - Sets the maximum size of the Diffie-Hellman parameters used for generating |
1795 | - the ephemeral/temporary Diffie-Hellman key in case of DHE key exchange. The |
1796 | - final size will try to match the size of the server's RSA (or DSA) key (e.g, |
1797 | - a 2048 bits temporary DH key for a 2048 bits RSA key), but will not exceed |
1798 | - this maximum value. Default value if 2048. Only 1024 or higher values are |
1799 | - allowed. Higher values will increase the CPU load, and values greater than |
1800 | - 1024 bits are not supported by Java 7 and earlier clients. This value is not |
1801 | - used if static Diffie-Hellman parameters are supplied either directly |
1802 | - in the certificate file or by using the ssl-dh-param-file parameter. |
1803 | - |
1804 | tune.ssl.ssl-ctx-cache-size <number> |
1805 | Sets the size of the cache used to store generated certificates to <number> |
1806 | entries. This is a LRU cache. Because generating a SSL certificate |
1807 | dynamically is expensive, they are cached. The default cache size is set to |
1808 | 1000 entries. |
1809 | |
1810 | -tune.ssl.capture-cipherlist-size <number> |
1811 | - Sets the maximum size of the buffer used for capturing client-hello cipher |
1812 | - list. If the value is 0 (default value) the capture is disabled, otherwise |
1813 | - a buffer is allocated for each SSL/TLS connection. |
1814 | - |
1815 | tune.vars.global-max-size <size> |
1816 | tune.vars.proc-max-size <size> |
1817 | tune.vars.reqres-max-size <size> |
1818 | @@ -3619,7 +3624,7 @@ http-error X X X X |
1819 | http-request - X X X |
1820 | http-response - X X X |
1821 | http-reuse X - X X |
1822 | -http-send-name-header - - X X |
1823 | +http-send-name-header X - X X |
1824 | id - X X X |
1825 | ignore-persist - - X X |
1826 | load-server-state-from-file X - X X |
1827 | @@ -3677,7 +3682,7 @@ option socket-stats (*) X X X - |
1828 | option splice-auto (*) X X X X |
1829 | option splice-request (*) X X X X |
1830 | option splice-response (*) X X X X |
1831 | -option spop-check - - - X |
1832 | +option spop-check X - X X |
1833 | option srvtcpka (*) X - X X |
1834 | option ssl-hello-chk X - X X |
1835 | -- keyword -------------------------- defaults - frontend - listen -- backend - |
1836 | @@ -6162,7 +6167,8 @@ http-request do-resolve(<var>,<resolvers>,[ipv4,ipv6]) <expr> : |
1837 | based on information found in the request (IE a Host header). |
1838 | If this action is used to find the server's IP address (using the |
1839 | "set-dst" action), then the server IP address in the backend must be set |
1840 | - to 0.0.0.0. |
1841 | + to 0.0.0.0. The do-resolve action takes an host-only parameter, any port must |
1842 | + be removed from the string. |
1843 | |
1844 | Example: |
1845 | resolvers mydns |
1846 | @@ -6177,7 +6183,7 @@ http-request do-resolve(<var>,<resolvers>,[ipv4,ipv6]) <expr> : |
1847 | |
1848 | frontend fe |
1849 | bind 10.42.0.1:80 |
1850 | - http-request do-resolve(txn.myip,mydns,ipv4) hdr(Host),lower |
1851 | + http-request do-resolve(txn.myip,mydns,ipv4) hdr(Host),lower,regsub(:[0-9]*$,) |
1852 | http-request capture var(txn.myip) len 40 |
1853 | |
1854 | # return 503 when the variable is not set, |
1855 | @@ -6814,9 +6820,11 @@ http-request set-uri <fmt> [ { if | unless } <condition> ] |
1856 | |
1857 | This rewrites the request URI with the result of the evaluation of format |
1858 | string <fmt>. The scheme, authority, path and query string are all replaced |
1859 | - at once. This can be used to rewrite hosts in front of proxies, or to |
1860 | - perform complex modifications to the URI such as moving parts between the |
1861 | - path and the query string. |
1862 | + at once. This can be used to rewrite hosts in front of proxies, or to perform |
1863 | + complex modifications to the URI such as moving parts between the path and |
1864 | + the query string. If an absolute URI is set, it will be sent as is to |
1865 | + HTTP/1.1 servers. If it is not the desired behavior, the host, the path |
1866 | + and/or the query string should be set separately. |
1867 | See also "http-request set-path" and "http-request set-query". |
1868 | |
1869 | http-request set-var(<var-name>) <expr> [ { if | unless } <condition> ] |
1870 | @@ -7541,7 +7549,26 @@ http-reuse { never | safe | aggressive | always } |
1871 | because almost no new connection will be established while idle connections |
1872 | remain available. This is particularly true with the "always" strategy. |
1873 | |
1874 | - See also : "option http-keep-alive", "server maxconn" |
1875 | + The rules to decide to keep an idle connection opened or to close it after |
1876 | + processing are also governed by the "tune.pool-low-fd-ratio" (default: 20%) |
1877 | + and "tune.pool-high-fd-ratio" (default: 25%). These correspond to the |
1878 | + percentage of total file descriptors spent in idle connections above which |
1879 | + haproxy will respectively refrain from keeping a connection opened after a |
1880 | + response, and actively kill idle connections. Some setups using a very high |
1881 | + ratio of idle connections, either because of too low a global "maxconn", or |
1882 | + due to a lot of HTTP/2 or HTTP/3 traffic on the frontend (few connections) |
1883 | + but HTTP/1 connections on the backend, may observe a lower reuse rate because |
1884 | + too few connections are kept open. It may be desirable in this case to adjust |
1885 | + such thresholds or simply to increase the global "maxconn" value. |
1886 | + |
1887 | + Similarly, when thread groups are explicitly enabled, it is important to |
1888 | + understand that idle connections are only usable between threads from a same |
1889 | + group. As such it may happen that unfair load between groups leads to more |
1890 | + idle connections being needed, causing a lower reuse rate. The same solution |
1891 | + may then be applied (increase global "maxconn" or increase pool ratios). |
1892 | + |
1893 | + See also : "option http-keep-alive", "server maxconn", "thread-groups", |
1894 | + "tune.pool-high-fd-ratio", "tune.pool-low-fd-ratio" |
1895 | |
1896 | |
1897 | http-send-name-header [<header>] |
1898 | @@ -8073,7 +8100,9 @@ monitor-uri <uri> |
1899 | Monitor requests are processed very early, just after the request is parsed |
1900 | and even before any "http-request". The only rulesets applied before are the |
1901 | tcp-request ones. They cannot be logged either, and it is the intended |
1902 | - purpose. They are only used to report HAProxy's health to an upper component, |
1903 | + purpose. Only one URI may be configured for monitoring; when multiple |
1904 | + "monitor-uri" statements are present, the last one will define the URI to |
1905 | + be used. They are only used to report HAProxy's health to an upper component, |
1906 | nothing more. However, it is possible to add any number of conditions using |
1907 | "monitor fail" and ACLs so that the result can be adjusted to whatever check |
1908 | can be imagined (most often the number of available servers in a backend). |
1909 | @@ -9350,7 +9379,7 @@ no option persist |
1910 | See also : "option redispatch", "retries", "force-persist" |
1911 | |
1912 | |
1913 | -option pgsql-check [ user <username> ] |
1914 | +option pgsql-check user <username> |
1915 | Use PostgreSQL health checks for server testing |
1916 | May be used in sections : defaults | frontend | listen | backend |
1917 | yes | no | yes | yes |
1918 | @@ -9610,7 +9639,7 @@ no option splice-response |
1919 | option spop-check |
1920 | Use SPOP health checks for server testing |
1921 | May be used in sections : defaults | frontend | listen | backend |
1922 | - no | no | no | yes |
1923 | + yes | no | yes | yes |
1924 | Arguments : none |
1925 | |
1926 | It is possible to test that the server correctly talks SPOP protocol instead |
1927 | @@ -10175,24 +10204,26 @@ redirect scheme <sch> [code <code>] <option> [{if | unless} <condition>] |
1928 | |
1929 | |
1930 | retries <value> |
1931 | - Set the number of retries to perform on a server after a connection failure |
1932 | + Set the number of retries to perform on a server after a failure |
1933 | May be used in sections: defaults | frontend | listen | backend |
1934 | yes | no | yes | yes |
1935 | Arguments : |
1936 | - <value> is the number of times a connection attempt should be retried on |
1937 | - a server when a connection either is refused or times out. The |
1938 | - default value is 3. |
1939 | + <value> is the number of times a request or connection attempt should be |
1940 | + retried on a server after a failure. |
1941 | |
1942 | - It is important to understand that this value applies to the number of |
1943 | - connection attempts, not full requests. When a connection has effectively |
1944 | - been established to a server, there will be no more retry. |
1945 | + By default, retries apply only to new connection attempts. However, when |
1946 | + the "retry-on" directive is used, other conditions might trigger a retry |
1947 | + (e.g. empty response, undesired status code), and each of them will count |
1948 | + one attempt, and when the total number attempts reaches the value here, an |
1949 | + error will be returned. |
1950 | |
1951 | In order to avoid immediate reconnections to a server which is restarting, |
1952 | a turn-around timer of min("timeout connect", one second) is applied before |
1953 | - a retry occurs. |
1954 | + a retry occurs on the same server. |
1955 | |
1956 | - When "option redispatch" is set, the last retry may be performed on another |
1957 | - server even if a cookie references a different server. |
1958 | + When "option redispatch" is set, some retries may be performed on another |
1959 | + server even if a cookie references a different server. By default this will |
1960 | + only be the last retry unless an argument is passed to "option redispatch". |
1961 | |
1962 | See also : "option redispatch" |
1963 | |
1964 | @@ -12423,7 +12454,7 @@ tcp-request content <action> [{if | unless} <condition>] |
1965 | evaluated. |
1966 | |
1967 | Example: |
1968 | - tcp-request content use-service lua.deny { src -f /etc/haproxy/blacklist.lst } |
1969 | + tcp-request content use-service lua.deny if { src -f /etc/haproxy/blacklist.lst } |
1970 | |
1971 | Example: |
1972 | |
1973 | @@ -14986,8 +15017,10 @@ sni <expression> |
1974 | The "sni" parameter evaluates the sample fetch expression, converts it to a |
1975 | string and uses the result as the host name sent in the SNI TLS extension to |
1976 | the server. A typical use case is to send the SNI received from the client in |
1977 | - a bridged HTTPS scenario, using the "ssl_fc_sni" sample fetch for the |
1978 | - expression, though alternatives such as req.hdr(host) can also make sense. If |
1979 | + a bridged TCP/SSL scenario, using the "ssl_fc_sni" sample fetch for the |
1980 | + expression. THIS MUST NOT BE USED FOR HTTPS, where req.hdr(host) should be |
1981 | + used instead, since SNI in HTTPS must always match the Host field and clients |
1982 | + are allowed to use different host names over the same connection). If |
1983 | "verify required" is set (which is the recommended setting), the resulting |
1984 | name will also be matched against the server certificate's names. See the |
1985 | "verify" directive for more details. If you want to set a SNI for health |
1986 | @@ -15679,7 +15712,11 @@ possible to convert the sample to lowercase before matching, like this : |
1987 | All ACL-specific criteria imply a default matching method. Most often, these |
1988 | criteria are composed by concatenating the name of the original sample fetch |
1989 | method and the matching method. For example, "hdr_beg" applies the "beg" match |
1990 | -to samples retrieved using the "hdr" fetch method. Since all ACL-specific |
1991 | +to samples retrieved using the "hdr" fetch method. This matching method is only |
1992 | +usable when the keyword is used alone, without any converter. In case any such |
1993 | +converter were to be applied after such an ACL keyword, the default matching |
1994 | +method from the ACL keyword is simply ignored since what will matter for the |
1995 | +matching is the output type of the last converter. Since all ACL-specific |
1996 | criteria rely on a sample fetch method, it is always possible instead to use |
1997 | the original sample fetch method and the explicit matching method using "-m". |
1998 | |
1999 | @@ -15805,13 +15842,24 @@ different forms : |
2000 | - suffix match (-m end) : the patterns are compared with the end of the |
2001 | extracted string, and the ACL matches if any of them matches. |
2002 | |
2003 | - - subdir match (-m dir) : the patterns are looked up inside the extracted |
2004 | - string, delimited with slashes ("/"), and the ACL matches if any of them |
2005 | - matches. |
2006 | - |
2007 | - - domain match (-m dom) : the patterns are looked up inside the extracted |
2008 | - string, delimited with dots ("."), and the ACL matches if any of them |
2009 | - matches. |
2010 | + - subdir match (-m dir) : the patterns are looked up anywhere inside the |
2011 | + extracted string, delimited with slashes ("/"), the beginning or the end |
2012 | + of the string. The ACL matches if any of them matches. As such, the string |
2013 | + "/images/png/logo/32x32.png", would match "/images", "/images/png", |
2014 | + "images/png", "/png/logo", "logo/32x32.png" or "32x32.png" but not "png" |
2015 | + nor "32x32". |
2016 | + |
2017 | + - domain match (-m dom) : the patterns are looked up anywhere inside the |
2018 | + extracted string, delimited with dots ("."), colons (":"), slashes ("/"), |
2019 | + question marks ("?"), the beginning or the end of the string. This is made |
2020 | + to be used with URLs. Leading and trailing delimiters in the pattern are |
2021 | + ignored. The ACL matches if any of them matches. As such, in the example |
2022 | + string "http://www1.dc-eu.example.com:80/blah", the patterns "http", |
2023 | + "www1", ".www1", "dc-eu", "example", "com", "80", "dc-eu.example", |
2024 | + "blah", ":www1:", "dc-eu.example:80" would match, but not "eu" nor "dc". |
2025 | + Using it to match domain suffixes for filtering or routing is generally |
2026 | + not a good idea, as the routing could easily be fooled by prepending the |
2027 | + matching prefix in front of another domain for example. |
2028 | |
2029 | String matching applies to verbatim strings as they are passed, with the |
2030 | exception of the backslash ("\") which makes it possible to escape some |
2031 | @@ -18860,6 +18908,16 @@ ssl_fc_sni : string |
2032 | requires that the SSL library is built with support for TLS extensions |
2033 | enabled (check haproxy -vv). |
2034 | |
2035 | + CAUTION! Except under very specific conditions, it is normally not correct to |
2036 | + use this field as a substitute for the HTTP "Host" header field. For example, |
2037 | + when forwarding an HTTPS connection to a server, the SNI field must be set |
2038 | + from the HTTP Host header field using "req.hdr(host)" and not from the front |
2039 | + SNI value. The reason is that SNI is solely used to select the certificate |
2040 | + the server side will present, and that clients are then allowed to send |
2041 | + requests with different Host values as long as they match the names in the |
2042 | + certificate. As such, "ssl_fc_sni" should normally not be used as an argument |
2043 | + to the "sni" server keyword, unless the backend works in TCP mode. |
2044 | + |
2045 | ACL derivatives : |
2046 | ssl_fc_sni_end : suffix match |
2047 | ssl_fc_sni_reg : regex match |
2048 | @@ -22093,8 +22151,8 @@ Optionally, a prefix could be used to force the address family and/or the |
2049 | socket type and the transport method. |
2050 | |
2051 | |
2052 | -11.1 Address family prefixes |
2053 | ----------------------------- |
2054 | +11.1. Address family prefixes |
2055 | +----------------------------- |
2056 | |
2057 | 'abns@<name>' following <name> is an abstract namespace (Linux only). |
2058 | |
2059 | @@ -22129,8 +22187,8 @@ socket type and the transport method. |
2060 | start by slash '/'. |
2061 | |
2062 | |
2063 | -11.2 Socket type prefixes |
2064 | -------------------------- |
2065 | +11.2. Socket type prefixes |
2066 | +-------------------------- |
2067 | |
2068 | Previous "Address family prefixes" can also be prefixed to force the socket |
2069 | type and the transport method. The default depends of the statement using |
2070 | @@ -22139,7 +22197,7 @@ This is the case for "log" statement where the default is syslog over UDP |
2071 | but we could force to use syslog over TCP. |
2072 | |
2073 | Those prefixes were designed for internal purpose and users should |
2074 | -instead use aliases of the next section "11.5.3 Protocol prefixes". |
2075 | +instead use aliases of the next section "11.3 Protocol prefixes". |
2076 | |
2077 | If users need one those prefixes to perform what they expect because |
2078 | they can not configure the same using the protocol prefixes, they should |
2079 | @@ -22152,8 +22210,8 @@ report this to the maintainers. |
2080 | to "datagram". |
2081 | |
2082 | |
2083 | -11.3 Protocol prefixes |
2084 | ----------------------- |
2085 | +11.3. Protocol prefixes |
2086 | +----------------------- |
2087 | |
2088 | 'tcp@<address>[:port1[-port2]]' following <address> is considered as an IPv4 |
2089 | or IPv6 address depending of the syntax but |
2090 | @@ -22190,14 +22248,14 @@ report this to the maintainers. |
2091 | method is forced to "datagram". Depending on |
2092 | the statement using this address, a port or |
2093 | port range can or must be specified. |
2094 | - It is considered as an alias of 'stream+ipv4@'. |
2095 | + It is considered as an alias of 'dgram+ipv4@'. |
2096 | |
2097 | 'udp6@<address>[:port1[-port2]]' following <address> is always considered as |
2098 | an IPv6 address but socket type and transport |
2099 | method is forced to "datagram". Depending on |
2100 | the statement using this address, a port or |
2101 | port range can or must be specified. |
2102 | - It is considered as an alias of 'stream+ipv4@'. |
2103 | + It is considered as an alias of 'dgram+ipv4@'. |
2104 | |
2105 | 'uxdg@<path>' following string is considered as a unix socket <path> but |
2106 | transport method is forced to "datagram". It is considered as |
2107 | diff --git a/doc/intro.txt b/doc/intro.txt |
2108 | index 325ba76..d6e8648 100644 |
2109 | --- a/doc/intro.txt |
2110 | +++ b/doc/intro.txt |
2111 | @@ -41,6 +41,7 @@ Summary |
2112 | 3.3.5. Load balancing |
2113 | 3.3.6. Stickiness |
2114 | 3.3.7. Logging |
2115 | +3.3.8. Statistics |
2116 | 3.4. Standard features |
2117 | 3.4.1. Sampling and converting information |
2118 | 3.4.2. Maps |
2119 | @@ -50,7 +51,6 @@ Summary |
2120 | 3.4.6. Formatted strings |
2121 | 3.4.7. HTTP rewriting and redirection |
2122 | 3.4.8. Server protection |
2123 | -3.4.9. Statistics |
2124 | 3.5. Advanced features |
2125 | 3.5.1. Management |
2126 | 3.5.2. System-specific capabilities |
2127 | diff --git a/doc/management.txt b/doc/management.txt |
2128 | index 56e4f66..56f119e 100644 |
2129 | --- a/doc/management.txt |
2130 | +++ b/doc/management.txt |
2131 | @@ -2919,6 +2919,10 @@ show ssl crt-list [-n] [<filename>] |
2132 | ecdsa.pem:3 [verify none allow-0rtt ssl-min-ver TLSv1.0 ssl-max-ver TLSv1.3] localhost !www.test1.com |
2133 | ecdsa.pem:4 [verify none allow-0rtt ssl-min-ver TLSv1.0 ssl-max-ver TLSv1.3] |
2134 | |
2135 | +show startup-logs |
2136 | + Dump all messages emitted during the startup of the current haproxy process, |
2137 | + each startup-logs buffer is unique to its haproxy worker. |
2138 | + |
2139 | show table |
2140 | Dump general information on all known stick-tables. Their name is returned |
2141 | (the name of the proxy which holds them), their type (currently zero, always |
2142 | diff --git a/doc/proxy-protocol.txt b/doc/proxy-protocol.txt |
2143 | index 4d49d5c..fac0331 100644 |
2144 | --- a/doc/proxy-protocol.txt |
2145 | +++ b/doc/proxy-protocol.txt |
2146 | @@ -500,7 +500,7 @@ protocol. Identifying the protocol version is easy : |
2147 | - if the incoming byte count is 16 or above and the 13 first bytes match |
2148 | the protocol signature block followed by the protocol version 2 : |
2149 | |
2150 | - \x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A\x02 |
2151 | + \x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A\x20 |
2152 | |
2153 | - otherwise, if the incoming byte count is 8 or above, and the 5 first |
2154 | characters match the US-ASCII representation of "PROXY" then the protocol |
2155 | diff --git a/include/haproxy/buf.h b/include/haproxy/buf.h |
2156 | index 6cfd9d3..fc7b6fb 100644 |
2157 | --- a/include/haproxy/buf.h |
2158 | +++ b/include/haproxy/buf.h |
2159 | @@ -445,7 +445,7 @@ static inline void b_slow_realign(struct buffer *b, char *swap, size_t output) |
2160 | |
2161 | /* process output data in two steps to cover wrapping */ |
2162 | if (block1 > b_size(b) - b_head_ofs(b)) { |
2163 | - block2 = b_size(b) - b_head_ofs(b); |
2164 | + block2 = b_peek_ofs(b, block1); |
2165 | block1 -= block2; |
2166 | } |
2167 | memcpy(swap + b_size(b) - output, b_head(b), block1); |
2168 | diff --git a/include/haproxy/bug.h b/include/haproxy/bug.h |
2169 | index a2a9f6d..445dd7c 100644 |
2170 | --- a/include/haproxy/bug.h |
2171 | +++ b/include/haproxy/bug.h |
2172 | @@ -42,8 +42,10 @@ static inline __attribute((always_inline)) void ha_crash_now(void) |
2173 | #if __GNUC_PREREQ__(5, 0) |
2174 | #pragma GCC diagnostic push |
2175 | #pragma GCC diagnostic ignored "-Warray-bounds" |
2176 | +#if __GNUC_PREREQ__(6, 0) |
2177 | #pragma GCC diagnostic ignored "-Wnull-dereference" |
2178 | #endif |
2179 | +#endif |
2180 | *(volatile char *)1 = 0; |
2181 | #if __GNUC_PREREQ__(5, 0) |
2182 | #pragma GCC diagnostic pop |
2183 | diff --git a/include/haproxy/http.h b/include/haproxy/http.h |
2184 | index d0f3fd2..8a86cb6 100644 |
2185 | --- a/include/haproxy/http.h |
2186 | +++ b/include/haproxy/http.h |
2187 | @@ -36,6 +36,8 @@ extern const uint8_t http_char_classes[256]; |
2188 | enum http_meth_t find_http_meth(const char *str, const int len); |
2189 | int http_get_status_idx(unsigned int status); |
2190 | const char *http_get_reason(unsigned int status); |
2191 | +struct ist http_get_host_port(const struct ist host); |
2192 | +int http_is_default_port(const struct ist schm, const struct ist port); |
2193 | int http_validate_scheme(const struct ist schm); |
2194 | struct ist http_get_scheme(const struct ist uri); |
2195 | struct ist http_get_authority(const struct ist uri, int no_userinfo); |
2196 | diff --git a/include/haproxy/listener-t.h b/include/haproxy/listener-t.h |
2197 | index c350290..476e65a 100644 |
2198 | --- a/include/haproxy/listener-t.h |
2199 | +++ b/include/haproxy/listener-t.h |
2200 | @@ -156,12 +156,21 @@ struct ssl_bind_conf { |
2201 | #endif |
2202 | }; |
2203 | |
2204 | +/* |
2205 | + * In OpenSSL 3.0.0, the biggest verify error code's value is 94 and on the |
2206 | + * latest 1.1.1 it already reaches 79 so we need to size the ca/crt-ignore-err |
2207 | + * arrays accordingly. If the max error code increases, the arrays might need to |
2208 | + * be resized. |
2209 | + */ |
2210 | +#define SSL_MAX_VFY_ERROR_CODE 94 |
2211 | +#define IGNERR_BF_SIZE ((SSL_MAX_VFY_ERROR_CODE >> 6) + 1) |
2212 | + |
2213 | /* "bind" line settings */ |
2214 | struct bind_conf { |
2215 | #ifdef USE_OPENSSL |
2216 | struct ssl_bind_conf ssl_conf; /* ssl conf for ctx setting */ |
2217 | - unsigned long long ca_ignerr; /* ignored verify errors in handshake if depth > 0 */ |
2218 | - unsigned long long crt_ignerr; /* ignored verify errors in handshake if depth == 0 */ |
2219 | + unsigned long long ca_ignerr_bitfield[IGNERR_BF_SIZE]; /* ignored verify errors in handshake if depth > 0 */ |
2220 | + unsigned long long crt_ignerr_bitfield[IGNERR_BF_SIZE]; /* ignored verify errors in handshake if depth == 0 */ |
2221 | SSL_CTX *initial_ctx; /* SSL context for initial negotiation */ |
2222 | SSL_CTX *default_ctx; /* SSL context of first/default certificate */ |
2223 | struct ssl_bind_conf *default_ssl_conf; /* custom SSL conf of default_ctx */ |
2224 | diff --git a/include/haproxy/listener.h b/include/haproxy/listener.h |
2225 | index 3fb078f..bb502c6 100644 |
2226 | --- a/include/haproxy/listener.h |
2227 | +++ b/include/haproxy/listener.h |
2228 | @@ -39,23 +39,29 @@ void listener_set_state(struct listener *l, enum li_state st); |
2229 | * closes upon SHUT_WR and refuses to rebind. So a common validation path |
2230 | * involves SHUT_WR && listen && SHUT_RD. In case of success, the FD's polling |
2231 | * is disabled. It normally returns non-zero, unless an error is reported. |
2232 | + * It will need to operate under the proxy's lock. The caller is |
2233 | + * responsible for indicating in lpx whether the proxy locks is |
2234 | + * already held (non-zero) or not (zero) so that the function picks it. |
2235 | */ |
2236 | -int pause_listener(struct listener *l); |
2237 | +int pause_listener(struct listener *l, int lpx); |
2238 | |
2239 | /* This function tries to resume a temporarily disabled listener. |
2240 | * The resulting state will either be LI_READY or LI_FULL. 0 is returned |
2241 | * in case of failure to resume (eg: dead socket). |
2242 | + * It will need to operate under the proxy's lock. The caller is |
2243 | + * responsible for indicating in lpx whether the proxy locks is |
2244 | + * already held (non-zero) or not (zero) so that the function picks it. |
2245 | */ |
2246 | -int resume_listener(struct listener *l); |
2247 | +int resume_listener(struct listener *l, int lpx); |
2248 | |
2249 | /* |
2250 | * This function completely stops a listener. It will need to operate under the |
2251 | - * proxy's lock, the protocol's lock, and the listener's lock. The caller is |
2252 | - * responsible for indicating in lpx, lpr, lli whether the respective locks are |
2253 | + * proxy's lock and the protocol's lock. The caller is |
2254 | + * responsible for indicating in lpx, lpr whether the respective locks are |
2255 | * already held (non-zero) or not (zero) so that the function picks the missing |
2256 | * ones, in this order. |
2257 | */ |
2258 | -void stop_listener(struct listener *l, int lpx, int lpr, int lli); |
2259 | +void stop_listener(struct listener *l, int lpx, int lpr); |
2260 | |
2261 | /* This function adds the specified listener's file descriptor to the polling |
2262 | * lists if it is in the LI_LISTEN state. The listener enters LI_READY or |
2263 | diff --git a/include/haproxy/peers-t.h b/include/haproxy/peers-t.h |
2264 | index ee9d905..93920fd 100644 |
2265 | --- a/include/haproxy/peers-t.h |
2266 | +++ b/include/haproxy/peers-t.h |
2267 | @@ -31,6 +31,7 @@ |
2268 | |
2269 | #include <haproxy/api-t.h> |
2270 | #include <haproxy/dict-t.h> |
2271 | +#include <haproxy/stick_table-t.h> |
2272 | #include <haproxy/thread-t.h> |
2273 | |
2274 | |
2275 | diff --git a/include/haproxy/pool.h b/include/haproxy/pool.h |
2276 | index 9264998..0547dcb 100644 |
2277 | --- a/include/haproxy/pool.h |
2278 | +++ b/include/haproxy/pool.h |
2279 | @@ -55,8 +55,8 @@ void pool_free_nocache(struct pool_head *pool, void *ptr); |
2280 | void dump_pools_to_trash(); |
2281 | void dump_pools(void); |
2282 | int pool_total_failures(); |
2283 | -unsigned long pool_total_allocated(); |
2284 | -unsigned long pool_total_used(); |
2285 | +unsigned long long pool_total_allocated(); |
2286 | +unsigned long long pool_total_used(); |
2287 | void pool_flush(struct pool_head *pool); |
2288 | void pool_gc(struct pool_head *pool_ctx); |
2289 | struct pool_head *create_pool(char *name, unsigned int size, unsigned int flags); |
2290 | diff --git a/include/haproxy/server.h b/include/haproxy/server.h |
2291 | index c927de3..fdb285c 100644 |
2292 | --- a/include/haproxy/server.h |
2293 | +++ b/include/haproxy/server.h |
2294 | @@ -45,6 +45,7 @@ extern struct dict server_key_dict; |
2295 | int srv_downtime(const struct server *s); |
2296 | int srv_lastsession(const struct server *s); |
2297 | int srv_getinter(const struct check *check); |
2298 | +void srv_settings_cpy(struct server *srv, const struct server *src, int srv_tmpl); |
2299 | int parse_server(const char *file, int linenum, char **args, struct proxy *curproxy, const struct proxy *defproxy, int parse_flags); |
2300 | int srv_update_addr(struct server *s, void *ip, int ip_sin_family, const char *updater); |
2301 | const char *srv_update_addr_port(struct server *s, const char *addr, const char *port, char *updater); |
2302 | @@ -254,18 +255,21 @@ static inline enum srv_initaddr srv_get_next_initaddr(unsigned int *list) |
2303 | |
2304 | static inline void srv_use_conn(struct server *srv, struct connection *conn) |
2305 | { |
2306 | - unsigned int curr; |
2307 | + unsigned int curr, prev; |
2308 | |
2309 | curr = _HA_ATOMIC_ADD_FETCH(&srv->curr_used_conns, 1); |
2310 | |
2311 | + |
2312 | /* It's ok not to do that atomically, we don't need an |
2313 | * exact max. |
2314 | */ |
2315 | - if (srv->max_used_conns < curr) |
2316 | - srv->max_used_conns = curr; |
2317 | + prev = HA_ATOMIC_LOAD(&srv->max_used_conns); |
2318 | + if (prev < curr) |
2319 | + HA_ATOMIC_STORE(&srv->max_used_conns, curr); |
2320 | |
2321 | - if (srv->est_need_conns < curr) |
2322 | - srv->est_need_conns = curr; |
2323 | + prev = HA_ATOMIC_LOAD(&srv->est_need_conns); |
2324 | + if (prev < curr) |
2325 | + HA_ATOMIC_STORE(&srv->est_need_conns, curr); |
2326 | } |
2327 | |
2328 | static inline void conn_delete_from_tree(struct ebmb_node *node) |
2329 | diff --git a/include/haproxy/sink.h b/include/haproxy/sink.h |
2330 | index 51d507c..a9f8099 100644 |
2331 | --- a/include/haproxy/sink.h |
2332 | +++ b/include/haproxy/sink.h |
2333 | @@ -28,6 +28,8 @@ |
2334 | |
2335 | extern struct list sink_list; |
2336 | |
2337 | +extern struct proxy *sink_proxies_list; |
2338 | + |
2339 | struct sink *sink_find(const char *name); |
2340 | struct sink *sink_new_fd(const char *name, const char *desc, enum log_fmt, int fd); |
2341 | ssize_t __sink_write(struct sink *sink, const struct ist msg[], size_t nmsg, |
2342 | diff --git a/include/haproxy/ssl_sock-t.h b/include/haproxy/ssl_sock-t.h |
2343 | index 974b836..35270ca 100644 |
2344 | --- a/include/haproxy/ssl_sock-t.h |
2345 | +++ b/include/haproxy/ssl_sock-t.h |
2346 | @@ -52,16 +52,20 @@ |
2347 | #define SSL_SOCK_SEND_UNLIMITED 0x00000004 |
2348 | #define SSL_SOCK_RECV_HEARTBEAT 0x00000008 |
2349 | |
2350 | -/* bits 0xFFFF0000 are reserved to store verify errors */ |
2351 | +/* bits 0xFFFFFF00 are reserved to store verify errors. |
2352 | + * The CA en CRT error codes will be stored on 7 bits each |
2353 | + * (since the max verify error code does not exceed 127) |
2354 | + * and the CA error depth will be stored on 4 bits. |
2355 | + */ |
2356 | |
2357 | /* Verify errors macros */ |
2358 | -#define SSL_SOCK_CA_ERROR_TO_ST(e) (((e > 63) ? 63 : e) << (16)) |
2359 | -#define SSL_SOCK_CAEDEPTH_TO_ST(d) (((d > 15) ? 15 : d) << (6+16)) |
2360 | -#define SSL_SOCK_CRTERROR_TO_ST(e) (((e > 63) ? 63 : e) << (4+6+16)) |
2361 | +#define SSL_SOCK_CA_ERROR_TO_ST(e) (((e > 127) ? 127 : e) << (8)) |
2362 | +#define SSL_SOCK_CAEDEPTH_TO_ST(d) (((d > 15) ? 15 : d) << (7+8)) |
2363 | +#define SSL_SOCK_CRTERROR_TO_ST(e) (((e > 127) ? 127 : e) << (4+7+8)) |
2364 | |
2365 | -#define SSL_SOCK_ST_TO_CA_ERROR(s) ((s >> (16)) & 63) |
2366 | -#define SSL_SOCK_ST_TO_CAEDEPTH(s) ((s >> (6+16)) & 15) |
2367 | -#define SSL_SOCK_ST_TO_CRTERROR(s) ((s >> (4+6+16)) & 63) |
2368 | +#define SSL_SOCK_ST_TO_CA_ERROR(s) ((s >> (8)) & 127) |
2369 | +#define SSL_SOCK_ST_TO_CAEDEPTH(s) ((s >> (7+8)) & 15) |
2370 | +#define SSL_SOCK_ST_TO_CRTERROR(s) ((s >> (4+7+8)) & 127) |
2371 | |
2372 | /* ssl_methods flags for ssl options */ |
2373 | #define MC_SSL_O_ALL 0x0000 |
2374 | diff --git a/include/haproxy/ssl_sock.h b/include/haproxy/ssl_sock.h |
2375 | index c68425a..9db4ec4 100644 |
2376 | --- a/include/haproxy/ssl_sock.h |
2377 | +++ b/include/haproxy/ssl_sock.h |
2378 | @@ -149,6 +149,29 @@ int ssl_sock_is_ssl(struct connection *conn) |
2379 | return 1; |
2380 | } |
2381 | |
2382 | +static inline int cert_ignerr_bitfield_get(const unsigned long long *bitfield, int bit_index) |
2383 | +{ |
2384 | + int byte_index = bit_index >> 6; |
2385 | + int val = 0; |
2386 | + |
2387 | + if (byte_index < IGNERR_BF_SIZE) |
2388 | + val = bitfield[byte_index] & (1ULL << (bit_index & 0x3F)); |
2389 | + |
2390 | + return val != 0; |
2391 | +} |
2392 | + |
2393 | +static inline void cert_ignerr_bitfield_set(unsigned long long *bitfield, int bit_index) |
2394 | +{ |
2395 | + int byte_index = bit_index >> 6; |
2396 | + |
2397 | + if (byte_index < IGNERR_BF_SIZE) |
2398 | + bitfield[byte_index] |= (1ULL << (bit_index & 0x3F)); |
2399 | +} |
2400 | + |
2401 | +static inline void cert_ignerr_bitfield_set_all(unsigned long long *bitfield) |
2402 | +{ |
2403 | + memset(bitfield, -1, IGNERR_BF_SIZE*sizeof(*bitfield)); |
2404 | +} |
2405 | |
2406 | #endif /* USE_OPENSSL */ |
2407 | #endif /* _HAPROXY_SSL_SOCK_H */ |
2408 | diff --git a/include/haproxy/stats-t.h b/include/haproxy/stats-t.h |
2409 | index 17641f5..920a311 100644 |
2410 | --- a/include/haproxy/stats-t.h |
2411 | +++ b/include/haproxy/stats-t.h |
2412 | @@ -443,7 +443,9 @@ enum stat_field { |
2413 | ST_F_USED_CONN_CUR, |
2414 | ST_F_NEED_CONN_EST, |
2415 | ST_F_UWEIGHT, |
2416 | + ST_F_AGG_SRV_STATUS, |
2417 | ST_F_AGG_SRV_CHECK_STATUS, |
2418 | + ST_F_AGG_CHECK_STATUS, |
2419 | |
2420 | /* must always be the last one */ |
2421 | ST_F_TOTAL_FIELDS |
2422 | diff --git a/include/haproxy/stream.h b/include/haproxy/stream.h |
2423 | index 1ec87b1..5a61c20 100644 |
2424 | --- a/include/haproxy/stream.h |
2425 | +++ b/include/haproxy/stream.h |
2426 | @@ -337,7 +337,7 @@ static inline void stream_choose_redispatch(struct stream *s) |
2427 | ((s->be->conn_retries - si->conn_retries) % |
2428 | (s->be->conn_retries + 1 + s->be->redispatch_after) == 0))) || |
2429 | (!(s->flags & SF_DIRECT) && s->be->srv_act > 1 && |
2430 | - ((s->be->lbprm.algo & BE_LB_KIND) == BE_LB_KIND_RR)))) { |
2431 | + ((s->be->lbprm.algo & BE_LB_KIND) != BE_LB_KIND_HI)))) { |
2432 | sess_change_server(s, NULL); |
2433 | if (may_dequeue_tasks(objt_server(s->target), s->be)) |
2434 | process_srv_queue(objt_server(s->target), 0); |
2435 | diff --git a/include/haproxy/task.h b/include/haproxy/task.h |
2436 | index d31c893..b3ffdf2 100644 |
2437 | --- a/include/haproxy/task.h |
2438 | +++ b/include/haproxy/task.h |
2439 | @@ -281,7 +281,7 @@ static inline struct task *task_unlink_wq(struct task *t) |
2440 | |
2441 | if (likely(task_in_wq(t))) { |
2442 | locked = t->state & TASK_SHARED_WQ; |
2443 | - BUG_ON(!locked && t->thread_mask != tid_bit); |
2444 | + BUG_ON(!locked && t->thread_mask != tid_bit && !(global.mode & MODE_STOPPING)); |
2445 | if (locked) |
2446 | HA_RWLOCK_WRLOCK(TASK_WQ_LOCK, &wq_lock); |
2447 | __task_unlink_wq(t); |
2448 | @@ -526,6 +526,7 @@ static inline void tasklet_init(struct tasklet *t) |
2449 | t->process = NULL; |
2450 | t->tid = -1; |
2451 | #ifdef DEBUG_TASK |
2452 | + t->call_date = 0; |
2453 | t->debug.caller_idx = 0; |
2454 | #endif |
2455 | LIST_INIT(&t->list); |
2456 | diff --git a/include/haproxy/tcpcheck-t.h b/include/haproxy/tcpcheck-t.h |
2457 | index 29cb4cc..439fe18 100644 |
2458 | --- a/include/haproxy/tcpcheck-t.h |
2459 | +++ b/include/haproxy/tcpcheck-t.h |
2460 | @@ -35,6 +35,7 @@ |
2461 | #define TCPCHK_OPT_DEFAULT_CONNECT 0x0008 /* Do a connect using server params */ |
2462 | #define TCPCHK_OPT_IMPLICIT 0x0010 /* Implicit connect */ |
2463 | #define TCPCHK_OPT_SOCKS4 0x0020 /* check the connection via socks4 proxy */ |
2464 | +#define TCPCHK_OPT_HAS_DATA 0x0040 /* data should be sent after conncetion */ |
2465 | |
2466 | enum tcpcheck_send_type { |
2467 | TCPCHK_SEND_UNDEF = 0, /* Send is not parsed. */ |
2468 | diff --git a/include/haproxy/tools.h b/include/haproxy/tools.h |
2469 | index a95844a..30b6bfa 100644 |
2470 | --- a/include/haproxy/tools.h |
2471 | +++ b/include/haproxy/tools.h |
2472 | @@ -406,7 +406,8 @@ char *encode_chunk(char *start, char *stop, |
2473 | |
2474 | /* |
2475 | * Tries to prefix characters tagged in the <map> with the <escape> |
2476 | - * character. The input <string> must be zero-terminated. The result will |
2477 | + * character. The input <string> is processed until string_stop |
2478 | + * is reached or NULL-byte is encountered. The result will |
2479 | * be stored between <start> (included) and <stop> (excluded). This |
2480 | * function will always try to terminate the resulting string with a '\0' |
2481 | * before <stop>, and will return its position if the conversion |
2482 | @@ -414,7 +415,7 @@ char *encode_chunk(char *start, char *stop, |
2483 | */ |
2484 | char *escape_string(char *start, char *stop, |
2485 | const char escape, const long *map, |
2486 | - const char *string); |
2487 | + const char *string, const char *string_stop); |
2488 | |
2489 | /* |
2490 | * Tries to prefix characters tagged in the <map> with the <escape> |
2491 | diff --git a/include/import/ebmbtree.h b/include/import/ebmbtree.h |
2492 | index f99c16b..2d63ed1 100644 |
2493 | --- a/include/import/ebmbtree.h |
2494 | +++ b/include/import/ebmbtree.h |
2495 | @@ -118,6 +118,59 @@ struct ebmb_node *ebmb_lookup_longest(struct eb_root *root, const void *x); |
2496 | struct ebmb_node *ebmb_lookup_prefix(struct eb_root *root, const void *x, unsigned int pfx); |
2497 | struct ebmb_node *ebmb_insert_prefix(struct eb_root *root, struct ebmb_node *new, unsigned int len); |
2498 | |
2499 | +/* start from a valid leaf and find the next matching prefix that's either a |
2500 | + * duplicate, or immediately shorter than the node's current one and still |
2501 | + * matches it. The purpose is to permit a caller that is not satisfied with a |
2502 | + * result provided by ebmb_lookup_longest() to evaluate the next matching |
2503 | + * entry. Given that shorter keys are necessarily attached to nodes located |
2504 | + * above the current one, it's sufficient to restart from the current leaf and |
2505 | + * go up until we find a shorter prefix, or a non-matching one. |
2506 | + */ |
2507 | +static inline struct ebmb_node *ebmb_lookup_shorter(struct ebmb_node *start) |
2508 | +{ |
2509 | + eb_troot_t *t = start->node.leaf_p; |
2510 | + struct ebmb_node *node; |
2511 | + |
2512 | + /* first, chcek for duplicates */ |
2513 | + node = ebmb_next_dup(start); |
2514 | + if (node) |
2515 | + return node; |
2516 | + |
2517 | + while (1) { |
2518 | + if (eb_gettag(t) == EB_LEFT) { |
2519 | + /* Walking up from left branch. We must ensure that we never |
2520 | + * walk beyond root. |
2521 | + */ |
2522 | + if (unlikely(eb_clrtag((eb_untag(t, EB_LEFT))->b[EB_RGHT]) == NULL)) |
2523 | + return NULL; |
2524 | + node = container_of(eb_root_to_node(eb_untag(t, EB_LEFT)), struct ebmb_node, node); |
2525 | + } else { |
2526 | + /* Walking up from right branch, so we cannot be below |
2527 | + * root. However, if we end up on a node with an even |
2528 | + * and positive bit, this is a cover node, which mandates |
2529 | + * that the left branch only contains cover values, so we |
2530 | + * must descend it. |
2531 | + */ |
2532 | + node = container_of(eb_root_to_node(eb_untag(t, EB_RGHT)), struct ebmb_node, node); |
2533 | + if (node->node.bit > 0 && !(node->node.bit & 1)) |
2534 | + return ebmb_entry(eb_walk_down(t, EB_LEFT), struct ebmb_node, node); |
2535 | + } |
2536 | + |
2537 | + /* Note that <t> cannot be NULL at this stage */ |
2538 | + t = node->node.node_p; |
2539 | + |
2540 | + /* this is a node attached to a deeper (and possibly different) |
2541 | + * leaf, not interesting for us. |
2542 | + */ |
2543 | + if (node->node.pfx >= start->node.pfx) |
2544 | + continue; |
2545 | + |
2546 | + if (check_bits(start->key, node->key, 0, node->node.pfx) == 0) |
2547 | + break; |
2548 | + } |
2549 | + return node; |
2550 | +} |
2551 | + |
2552 | /* The following functions are less likely to be used directly, because their |
2553 | * code is larger. The non-inlined version is preferred. |
2554 | */ |
2555 | diff --git a/reg-tests/cache/if-modified-since.vtc b/reg-tests/cache/if-modified-since.vtc |
2556 | index 8ae1cce..387fc7e 100644 |
2557 | --- a/reg-tests/cache/if-modified-since.vtc |
2558 | +++ b/reg-tests/cache/if-modified-since.vtc |
2559 | @@ -62,6 +62,10 @@ haproxy h1 -conf { |
2560 | server www ${s1_addr}:${s1_port} |
2561 | http-response cache-store my_cache |
2562 | |
2563 | + # Remove Transfer-Encoding header because of a vtest issue with |
2564 | + # 304-Not-Modified responses |
2565 | + http-after-response del-header transfer-encoding if { status eq 304 } |
2566 | + |
2567 | cache my_cache |
2568 | total-max-size 3 |
2569 | max-age 20 |
2570 | @@ -149,4 +153,3 @@ client c1 -connect ${h1_fe_sock} { |
2571 | expect resp.bodylen == 0 |
2572 | |
2573 | } -run |
2574 | - |
2575 | diff --git a/reg-tests/cache/if-none-match.vtc b/reg-tests/cache/if-none-match.vtc |
2576 | index ba3336a..bc7d67b 100644 |
2577 | --- a/reg-tests/cache/if-none-match.vtc |
2578 | +++ b/reg-tests/cache/if-none-match.vtc |
2579 | @@ -47,6 +47,10 @@ haproxy h1 -conf { |
2580 | server www ${s1_addr}:${s1_port} |
2581 | http-response cache-store my_cache |
2582 | |
2583 | + # Remove Transfer-Encoding header because of a vtest issue with |
2584 | + # 304-Not-Modified responses |
2585 | + http-after-response del-header transfer-encoding if { status eq 304 } |
2586 | + |
2587 | cache my_cache |
2588 | total-max-size 3 |
2589 | max-age 20 |
2590 | diff --git a/reg-tests/checks/4be_1srv_smtpchk_httpchk_layer47errors.vtc b/reg-tests/checks/4be_1srv_smtpchk_httpchk_layer47errors.vtc |
2591 | index f9f37a1..ea72701 100644 |
2592 | --- a/reg-tests/checks/4be_1srv_smtpchk_httpchk_layer47errors.vtc |
2593 | +++ b/reg-tests/checks/4be_1srv_smtpchk_httpchk_layer47errors.vtc |
2594 | @@ -8,7 +8,7 @@ barrier b cond 3 |
2595 | |
2596 | syslog S1 -level notice { |
2597 | recv |
2598 | - 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." |
2599 | + expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be1/srv1 succeeded.+reason: Layer7 check passed.+code: 221.+check duration: [[:digit:]]+ms.+status: 1/1 UP." |
2600 | barrier b sync |
2601 | recv |
2602 | expect ~ "Health check for server be1/srv1 failed.+reason: Layer7 timeout.+check duration: [[:digit:]]+ms.+status: 0/1 DOWN" |
2603 | @@ -36,12 +36,17 @@ server s1 { |
2604 | send "2" |
2605 | send "2" |
2606 | send "0" |
2607 | - send "\r\n\r\n" |
2608 | + send "\r\n" |
2609 | recv 16 |
2610 | send "2" |
2611 | send "4" |
2612 | send "8" |
2613 | - send "\r\n\r\n" |
2614 | + send "\r\n" |
2615 | + recv 6 |
2616 | + send "2" |
2617 | + send "2" |
2618 | + send "1" |
2619 | + send " ok\r\n" |
2620 | } -start |
2621 | |
2622 | server s2 { |
2623 | diff --git a/reg-tests/checks/pgsql-check.vtc b/reg-tests/checks/pgsql-check.vtc |
2624 | index 968a18c..05c5a71 100644 |
2625 | --- a/reg-tests/checks/pgsql-check.vtc |
2626 | +++ b/reg-tests/checks/pgsql-check.vtc |
2627 | @@ -23,6 +23,11 @@ server s3 { |
2628 | send "Not a PostgreSQL response" |
2629 | } -start |
2630 | |
2631 | +server s4 { |
2632 | + recv 23 |
2633 | + sendhex "52000000170000000A534352414D2D5348412D3235360000" |
2634 | +} -start |
2635 | + |
2636 | syslog S1 -level notice { |
2637 | recv |
2638 | 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." |
2639 | @@ -38,6 +43,10 @@ syslog S3 -level notice { |
2640 | 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." |
2641 | } -start |
2642 | |
2643 | +syslog S4 -level notice { |
2644 | + recv |
2645 | + 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." |
2646 | +} -start |
2647 | |
2648 | haproxy h1 -conf { |
2649 | defaults |
2650 | @@ -64,6 +73,12 @@ haproxy h1 -conf { |
2651 | option pgsql-check user postgres |
2652 | server srv ${s3_addr}:${s3_port} check inter 1s rise 1 fall 1 |
2653 | |
2654 | + backend be4 |
2655 | + log ${S4_addr}:${S4_port} daemon |
2656 | + option log-health-checks |
2657 | + option pgsql-check user postgres |
2658 | + server srv ${s4_addr}:${s4_port} check inter 1s rise 1 fall 1 |
2659 | + |
2660 | listen pgsql1 |
2661 | bind "fd@${pgsql}" |
2662 | tcp-request inspect-delay 100ms |
2663 | @@ -75,3 +90,4 @@ haproxy h1 -conf { |
2664 | syslog S1 -wait |
2665 | syslog S2 -wait |
2666 | syslog S3 -wait |
2667 | +syslog S4 -wait |
2668 | diff --git a/reg-tests/checks/smtp-check.vtc b/reg-tests/checks/smtp-check.vtc |
2669 | index 29d0ddb..9d8bb8a 100644 |
2670 | --- a/reg-tests/checks/smtp-check.vtc |
2671 | +++ b/reg-tests/checks/smtp-check.vtc |
2672 | @@ -10,6 +10,8 @@ server s1 { |
2673 | send "220 smtp-check.vtc SMTP Server\r\n" |
2674 | recv 16 |
2675 | send "250 smtp-check.vtc\r\n" |
2676 | + recv 6 |
2677 | + send "221 smtp-check.vtc closing\r\n" |
2678 | } -start |
2679 | |
2680 | server s2 { |
2681 | @@ -18,6 +20,8 @@ server s2 { |
2682 | send "250-smtp-check.vtc\r\n" |
2683 | send "250-KEYWORD\r\n" |
2684 | send "250 LAST KEYWORD\r\n" |
2685 | + recv 6 |
2686 | + send "221 smtp-check.vtc closing\r\n" |
2687 | } -start |
2688 | |
2689 | server s3 { |
2690 | @@ -36,12 +40,12 @@ server s5 { |
2691 | |
2692 | syslog S1 -level notice { |
2693 | recv |
2694 | - 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." |
2695 | + 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." |
2696 | } -start |
2697 | |
2698 | syslog S2 -level notice { |
2699 | recv |
2700 | - 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." |
2701 | + 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." |
2702 | } -start |
2703 | |
2704 | syslog S3 -level notice { |
2705 | diff --git a/reg-tests/contrib/prometheus.vtc b/reg-tests/contrib/prometheus.vtc |
2706 | index ebe0b87..766db47 100644 |
2707 | --- a/reg-tests/contrib/prometheus.vtc |
2708 | +++ b/reg-tests/contrib/prometheus.vtc |
2709 | @@ -8,12 +8,12 @@ feature ignore_unknown_macro |
2710 | server s1 { |
2711 | rxreq |
2712 | txresp |
2713 | -} -repeat 2 -start |
2714 | +} -start |
2715 | |
2716 | server s2 { |
2717 | rxreq |
2718 | txresp |
2719 | -} -repeat 2 -start |
2720 | +} -start |
2721 | |
2722 | haproxy h1 -conf { |
2723 | defaults |
2724 | @@ -33,8 +33,9 @@ haproxy h1 -conf { |
2725 | |
2726 | backend be |
2727 | stick-table type ip size 1m expire 10s store http_req_rate(10s) |
2728 | + option httpchk |
2729 | server s1 ${s1_addr}:${s1_port} |
2730 | - server s2 ${s2_addr}:${s2_port} check maxqueue 10 maxconn 12 pool-max-conn 42 |
2731 | + server s2 ${s2_addr}:${s2_port} check inter 5s maxqueue 10 maxconn 12 pool-max-conn 42 |
2732 | } -start |
2733 | |
2734 | client c1 -connect ${h1_stats_sock} { |
2735 | diff --git a/reg-tests/converter/digest.vtc b/reg-tests/converter/digest.vtc |
2736 | index a14f1cc..511daca 100644 |
2737 | --- a/reg-tests/converter/digest.vtc |
2738 | +++ b/reg-tests/converter/digest.vtc |
2739 | @@ -7,7 +7,7 @@ feature ignore_unknown_macro |
2740 | |
2741 | server s1 { |
2742 | rxreq |
2743 | - txresp |
2744 | + txresp -hdr "Connection: close" |
2745 | } -repeat 2 -start |
2746 | |
2747 | haproxy h1 -conf { |
2748 | diff --git a/reg-tests/converter/hmac.vtc b/reg-tests/converter/hmac.vtc |
2749 | index f9d9d35..391e04a 100644 |
2750 | --- a/reg-tests/converter/hmac.vtc |
2751 | +++ b/reg-tests/converter/hmac.vtc |
2752 | @@ -7,7 +7,7 @@ feature ignore_unknown_macro |
2753 | |
2754 | server s1 { |
2755 | rxreq |
2756 | - txresp |
2757 | + txresp -hdr "Connection: close" |
2758 | } -repeat 2 -start |
2759 | |
2760 | haproxy h1 -conf { |
2761 | diff --git a/reg-tests/converter/iif.vtc b/reg-tests/converter/iif.vtc |
2762 | index 22414e0..3a6d6a6 100644 |
2763 | --- a/reg-tests/converter/iif.vtc |
2764 | +++ b/reg-tests/converter/iif.vtc |
2765 | @@ -5,7 +5,7 @@ feature ignore_unknown_macro |
2766 | |
2767 | server s1 { |
2768 | rxreq |
2769 | - txresp |
2770 | + txresp -hdr "Connection: close" |
2771 | } -repeat 3 -start |
2772 | |
2773 | haproxy h1 -conf { |
2774 | diff --git a/reg-tests/converter/json_query.vtc b/reg-tests/converter/json_query.vtc |
2775 | index b420942..9db77eb 100644 |
2776 | --- a/reg-tests/converter/json_query.vtc |
2777 | +++ b/reg-tests/converter/json_query.vtc |
2778 | @@ -5,7 +5,7 @@ feature ignore_unknown_macro |
2779 | |
2780 | server s1 { |
2781 | rxreq |
2782 | - txresp |
2783 | + txresp -hdr "Connection: close" |
2784 | } -repeat 8 -start |
2785 | |
2786 | haproxy h1 -conf { |
2787 | diff --git a/reg-tests/http-messaging/h1_host_normalization.vtc b/reg-tests/http-messaging/h1_host_normalization.vtc |
2788 | new file mode 100644 |
2789 | index 0000000..6ea32d2 |
2790 | --- /dev/null |
2791 | +++ b/reg-tests/http-messaging/h1_host_normalization.vtc |
2792 | @@ -0,0 +1,276 @@ |
2793 | +varnishtest "H1 authority validation and host normalizarion based on the scheme (rfc3982 6.3.2) or the method (connect)" |
2794 | + |
2795 | +#REQUIRE_VERSION=2.4 |
2796 | +feature ignore_unknown_macro |
2797 | + |
2798 | +syslog S1 -level info { |
2799 | + # C1 |
2800 | + recv |
2801 | + expect ~ "^.* uri: GET http://toto:poue@hostname/c1 HTTP/1.1; host: {hostname}$" |
2802 | + |
2803 | + # C2 |
2804 | + recv |
2805 | + expect ~ "^.* uri: GET http://hostname:8080/c2 HTTP/1.1; host: {hostname:8080}$" |
2806 | + |
2807 | + # C3 |
2808 | + recv |
2809 | + expect ~ "^.* uri: GET https://hostname/c3 HTTP/1.1; host: {hostname}$" |
2810 | + |
2811 | + # C4 |
2812 | + recv |
2813 | + expect ~ "^.* uri: GET https://hostname:80/c4 HTTP/1.1; host: {hostname:80}$" |
2814 | + |
2815 | + # C5 |
2816 | + recv |
2817 | + expect ~ "^.* uri: CONNECT hostname:80 HTTP/1.1; host: {hostname}$" |
2818 | + recv |
2819 | + expect ~ "^.* uri: CONNECT hostname:80 HTTP/1.1; host: {hostname}$" |
2820 | + |
2821 | + # C6 |
2822 | + recv |
2823 | + expect ~ "^.* uri: CONNECT hostname:443 HTTP/1.1; host: {hostname}$" |
2824 | + recv |
2825 | + expect ~ "^.* uri: CONNECT hostname:443 HTTP/1.1; host: {hostname}$" |
2826 | + |
2827 | + recv |
2828 | + expect ~ "^.* uri: CONNECT hostname:8443 HTTP/1.1; host: {hostname:8443}$" |
2829 | +} -start |
2830 | + |
2831 | +haproxy h1 -conf { |
2832 | + defaults |
2833 | + mode http |
2834 | + timeout connect 1s |
2835 | + timeout client 1s |
2836 | + timeout server 1s |
2837 | + |
2838 | + frontend fe |
2839 | + bind "fd@${fe}" |
2840 | + |
2841 | + http-request capture req.hdr(host) len 512 |
2842 | + log-format "uri: %r; host: %hr" |
2843 | + log ${S1_addr}:${S1_port} len 2048 local0 debug err |
2844 | + |
2845 | + http-request return status 200 |
2846 | +} -start |
2847 | + |
2848 | +# default port 80 with http scheme => should be normalized |
2849 | +# Be sure userinfo are skipped |
2850 | +client c1 -connect ${h1_fe_sock} { |
2851 | + txreq \ |
2852 | + -req "GET" \ |
2853 | + -url "http://toto:poue@hostname:80/c1" \ |
2854 | + -hdr "host: hostname:80" |
2855 | + |
2856 | + rxresp |
2857 | + expect resp.status == 200 |
2858 | +} -run |
2859 | + |
2860 | +# port 8080 with http scheme => no normalization |
2861 | +client c2 -connect ${h1_fe_sock} { |
2862 | + txreq \ |
2863 | + -req "GET" \ |
2864 | + -url "http://hostname:8080/c2" \ |
2865 | + -hdr "host: hostname:8080" |
2866 | + |
2867 | + rxresp |
2868 | + expect resp.status == 200 |
2869 | +} -run |
2870 | + |
2871 | +# default port 443 with https scheme => should be normalized |
2872 | +client c3 -connect ${h1_fe_sock} { |
2873 | + txreq \ |
2874 | + -req "GET" \ |
2875 | + -url "https://hostname:443/c3" \ |
2876 | + -hdr "host: hostname:443" |
2877 | + |
2878 | + rxresp |
2879 | + expect resp.status == 200 |
2880 | +} -run |
2881 | + |
2882 | +# port 80 with https scheme => no normalization |
2883 | +client c4 -connect ${h1_fe_sock} { |
2884 | + txreq \ |
2885 | + -req "GET" \ |
2886 | + -url "https://hostname:80/c4" \ |
2887 | + -hdr "host: hostname:80" |
2888 | + |
2889 | + rxresp |
2890 | + expect resp.status == 200 |
2891 | +} -run |
2892 | + |
2893 | +# CONNECT on port 80 => should be normalized |
2894 | +client c5 -connect ${h1_fe_sock} { |
2895 | + txreq \ |
2896 | + -req "CONNECT" \ |
2897 | + -url "hostname:80" \ |
2898 | + -hdr "host: hostname:80" |
2899 | + |
2900 | + rxresp |
2901 | + expect resp.status == 200 |
2902 | +} -run |
2903 | +client c5 -connect ${h1_fe_sock} { |
2904 | + |
2905 | + txreq \ |
2906 | + -req "CONNECT" \ |
2907 | + -url "hostname:80" \ |
2908 | + -hdr "host: hostname" |
2909 | + |
2910 | + rxresp |
2911 | + expect resp.status == 200 |
2912 | +} -run |
2913 | + |
2914 | +# CONNECT on port 443 => should be normalized |
2915 | +client c6 -connect ${h1_fe_sock} { |
2916 | + txreq \ |
2917 | + -req "CONNECT" \ |
2918 | + -url "hostname:443" \ |
2919 | + -hdr "host: hostname:443" |
2920 | + |
2921 | + rxresp |
2922 | + expect resp.status == 200 |
2923 | +} -run |
2924 | +client c6 -connect ${h1_fe_sock} { |
2925 | + txreq \ |
2926 | + -req "CONNECT" \ |
2927 | + -url "hostname:443" \ |
2928 | + -hdr "host: hostname" |
2929 | + |
2930 | + rxresp |
2931 | + expect resp.status == 200 |
2932 | +} -run |
2933 | + |
2934 | +# CONNECT on port non-default port => no normalization |
2935 | +client c7 -connect ${h1_fe_sock} { |
2936 | + txreq \ |
2937 | + -req "CONNECT" \ |
2938 | + -url "hostname:8443" \ |
2939 | + -hdr "host: hostname:8443" |
2940 | + |
2941 | + rxresp |
2942 | + expect resp.status == 200 |
2943 | +} -run |
2944 | + |
2945 | +# host miss-match => error |
2946 | +client c8 -connect ${h1_fe_sock} { |
2947 | + txreq \ |
2948 | + -req "GET" \ |
2949 | + -url "http://hostname1/" \ |
2950 | + -hdr "host: hostname2" |
2951 | + |
2952 | + rxresp |
2953 | + expect resp.status == 400 |
2954 | +} -run |
2955 | + |
2956 | +# port miss-match => error |
2957 | +client c9 -connect ${h1_fe_sock} { |
2958 | + txreq \ |
2959 | + -req "GET" \ |
2960 | + -url "http://hostname:80/" \ |
2961 | + -hdr "host: hostname:81" |
2962 | + |
2963 | + rxresp |
2964 | + expect resp.status == 400 |
2965 | +} -run |
2966 | + |
2967 | +# no host port with a non-default port in abs-uri => error |
2968 | +client c10 -connect ${h1_fe_sock} { |
2969 | + txreq \ |
2970 | + -req "GET" \ |
2971 | + -url "http://hostname:8080/" \ |
2972 | + -hdr "host: hostname" |
2973 | + |
2974 | + rxresp |
2975 | + expect resp.status == 400 |
2976 | +} -run |
2977 | + |
2978 | +# non-default host port with a default in abs-uri => error |
2979 | +client c11 -connect ${h1_fe_sock} { |
2980 | + txreq \ |
2981 | + -req "GET" \ |
2982 | + -url "http://hostname/" \ |
2983 | + -hdr "host: hostname:81" |
2984 | + |
2985 | + rxresp |
2986 | + expect resp.status == 400 |
2987 | +} -run |
2988 | + |
2989 | +# miss-match between host headers => error |
2990 | +client c12 -connect ${h1_fe_sock} { |
2991 | + txreq \ |
2992 | + -req "GET" \ |
2993 | + -url "http://hostname1/" \ |
2994 | + -hdr "host: hostname1" \ |
2995 | + -hdr "host: hostname2" |
2996 | + |
2997 | + rxresp |
2998 | + expect resp.status == 400 |
2999 | +} -run |
3000 | + |
3001 | +# miss-match between host headers but with a normalization => error |
3002 | +client c13 -connect ${h1_fe_sock} { |
3003 | + txreq \ |
3004 | + -req "GET" \ |
3005 | + -url "http://hostname1/" \ |
3006 | + -hdr "host: hostname1:80" \ |
3007 | + -hdr "host: hostname1" |
3008 | + |
3009 | + rxresp |
3010 | + expect resp.status == 400 |
3011 | +} -run |
3012 | + |
3013 | +# CONNECT authoriy without port => error |
3014 | +client c14 -connect ${h1_fe_sock} { |
3015 | + txreq \ |
3016 | + -req "CONNECT" \ |
3017 | + -url "hostname" \ |
3018 | + -hdr "host: hostname" |
3019 | + |
3020 | + rxresp |
3021 | + expect resp.status == 400 |
3022 | +} -run |
3023 | + |
3024 | +# host miss-match with CONNECT => error |
3025 | +client c15 -connect ${h1_fe_sock} { |
3026 | + txreq \ |
3027 | + -req "CONNECT" \ |
3028 | + -url "hostname1:80" \ |
3029 | + -hdr "host: hostname2:80" |
3030 | + |
3031 | + rxresp |
3032 | + expect resp.status == 400 |
3033 | +} -run |
3034 | + |
3035 | +# port miss-match with CONNECT => error |
3036 | +client c16 -connect ${h1_fe_sock} { |
3037 | + txreq \ |
3038 | + -req "CONNECT" \ |
3039 | + -url "hostname:80" \ |
3040 | + -hdr "host: hostname:443" |
3041 | + |
3042 | + rxresp |
3043 | + expect resp.status == 400 |
3044 | +} -run |
3045 | + |
3046 | +# no host port with non-default port in CONNECT authority => error |
3047 | +client c17 -connect ${h1_fe_sock} { |
3048 | + txreq \ |
3049 | + -req "CONNECT" \ |
3050 | + -url "hostname:8080" \ |
3051 | + -hdr "host: hostname" |
3052 | + |
3053 | + rxresp |
3054 | + expect resp.status == 400 |
3055 | +} -run |
3056 | + |
3057 | +# no authority => error |
3058 | +client c18 -connect ${h1_fe_sock} { |
3059 | + txreq \ |
3060 | + -req "CONNECT" \ |
3061 | + -url "/" \ |
3062 | + -hdr "host: hostname" |
3063 | + |
3064 | + rxresp |
3065 | + expect resp.status == 400 |
3066 | +} -run |
3067 | + |
3068 | +syslog S1 -wait |
3069 | diff --git a/reg-tests/http-messaging/http_request_buffer.vtc b/reg-tests/http-messaging/http_request_buffer.vtc |
3070 | index f1cec1a..e712e32 100644 |
3071 | --- a/reg-tests/http-messaging/http_request_buffer.vtc |
3072 | +++ b/reg-tests/http-messaging/http_request_buffer.vtc |
3073 | @@ -9,6 +9,8 @@ feature ignore_unknown_macro |
3074 | # thanks to "http-buffer-request". If this was the case, c2 client |
3075 | # could not connect to s1 server and this would lead to make this test fail. |
3076 | |
3077 | +barrier b1 cond 2 -cyclic |
3078 | + |
3079 | server s1 { |
3080 | rxreq |
3081 | expect req.bodylen == 257 |
3082 | @@ -23,11 +25,17 @@ server s1 { |
3083 | |
3084 | syslog S -level info { |
3085 | recv |
3086 | - 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\"" |
3087 | + 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\"" |
3088 | + barrier b1 sync |
3089 | + |
3090 | recv |
3091 | expect ~ "[^:\\[ ]*\\[[0-9]*\\]: .* .* fe1 be1/srv1 [0-9]*/[0-9]*/[0-9]*/[0-9]*/[0-9]* 200 .* - - ---- .* .* \"GET / HTTP/1\\.1\"" |
3092 | + barrier b1 sync |
3093 | + |
3094 | recv |
3095 | expect ~ "[^:\\[ ]*\\[[0-9]*\\]: .* .* fe2 be1/srv1 [0-9]*/[0-9]*/[0-9]*/[0-9]*/[0-9]* 200 .* - - ---- .* .* \"POST /1 HTTP/1\\.1\"" |
3096 | + barrier b1 sync |
3097 | + |
3098 | recv |
3099 | expect ~ "[^:\\[ ]*\\[[0-9]*\\]: .* .* fe2 be1/<NOSRV> [0-9]*/-1/-1/-1/[0-9]* -1 .* - - CR-- .* .* \"POST /2 HTTP/1\\.1\"" |
3100 | } -start |
3101 | @@ -88,6 +96,9 @@ client c1 -connect ${h1_fe1_sock} { |
3102 | expect resp.status == 408 |
3103 | } -run |
3104 | |
3105 | +# Wait matching on log message |
3106 | +barrier b1 sync |
3107 | + |
3108 | # Payload is fully sent |
3109 | # ==> Request must be sent to the server. A 200 must be received |
3110 | client c2 -connect ${h1_fe1_sock} { |
3111 | @@ -96,6 +107,9 @@ client c2 -connect ${h1_fe1_sock} { |
3112 | expect resp.status == 200 |
3113 | } -run |
3114 | |
3115 | +# Wait matching on log message |
3116 | +barrier b1 sync |
3117 | + |
3118 | # Payload is fully sent in 2 steps (with a small delay, smaller than the client |
3119 | # timeout) and splitted on a chunk size. |
3120 | # ==> Request must be sent to the server. A 200 must be received |
3121 | @@ -107,6 +121,9 @@ client c3 -connect ${h1_fe2_sock} { |
3122 | expect resp.status == 200 |
3123 | } -run |
3124 | |
3125 | +# Wait matching on log message |
3126 | +barrier b1 sync |
3127 | + |
3128 | # Last CRLF of the request payload is missing but payload is sent in 2 steps |
3129 | # (with a small delay, smaller than the client timeout) and splitted on a chunk |
3130 | # size. The client aborts before sending the last CRLF. |
3131 | diff --git a/reg-tests/http-rules/restrict_req_hdr_names.vtc b/reg-tests/http-rules/restrict_req_hdr_names.vtc |
3132 | index 57bc7e1..b493c84 100644 |
3133 | --- a/reg-tests/http-rules/restrict_req_hdr_names.vtc |
3134 | +++ b/reg-tests/http-rules/restrict_req_hdr_names.vtc |
3135 | @@ -35,6 +35,32 @@ server s5 { |
3136 | txresp |
3137 | } -start |
3138 | |
3139 | +server s6 { |
3140 | + rxreq |
3141 | + expect req.http.x_my_hdr_with_lots_of_underscores == <undef> |
3142 | + txresp |
3143 | +} -start |
3144 | + |
3145 | +server s7 { |
3146 | + rxreq |
3147 | + expect req.http.x_my_hdr-1 == <undef> |
3148 | + expect req.http.x-my-hdr-2 == on |
3149 | + txresp |
3150 | +} -start |
3151 | + |
3152 | +server s8 { |
3153 | + rxreq |
3154 | + expect req.http.x-my_hdr-1 == <undef> |
3155 | + expect req.http.x-my_hdr-2 == <undef> |
3156 | + txresp |
3157 | +} -start |
3158 | + |
3159 | +server s9 { |
3160 | + rxreq |
3161 | + expect req.http.x-my-hdr-with-trailing-underscore_ == <undef> |
3162 | + txresp |
3163 | +} -start |
3164 | + |
3165 | haproxy h1 -conf { |
3166 | defaults |
3167 | mode http |
3168 | @@ -50,6 +76,10 @@ haproxy h1 -conf { |
3169 | use_backend be-fcgi1 if { path /req4 } |
3170 | use_backend be-fcgi2 if { path /req5 } |
3171 | use_backend be-fcgi3 if { path /req6 } |
3172 | + use_backend be-http4 if { path /req7 } |
3173 | + use_backend be-http5 if { path /req8 } |
3174 | + use_backend be-http6 if { path /req9 } |
3175 | + use_backend be-http7 if { path /req10 } |
3176 | |
3177 | backend be-http1 |
3178 | server s1 ${s1_addr}:${s1_port} |
3179 | @@ -72,6 +102,22 @@ haproxy h1 -conf { |
3180 | backend be-fcgi3 |
3181 | option http-restrict-req-hdr-names reject |
3182 | |
3183 | + backend be-http4 |
3184 | + option http-restrict-req-hdr-names delete |
3185 | + server s6 ${s6_addr}:${s6_port} |
3186 | + |
3187 | + backend be-http5 |
3188 | + option http-restrict-req-hdr-names delete |
3189 | + server s7 ${s7_addr}:${s7_port} |
3190 | + |
3191 | + backend be-http6 |
3192 | + option http-restrict-req-hdr-names delete |
3193 | + server s8 ${s8_addr}:${s8_port} |
3194 | + |
3195 | + backend be-http7 |
3196 | + option http-restrict-req-hdr-names delete |
3197 | + server s9 ${s9_addr}:${s9_port} |
3198 | + |
3199 | defaults |
3200 | mode http |
3201 | timeout connect 1s |
3202 | @@ -114,6 +160,22 @@ client c1 -connect ${h1_fe1_sock} { |
3203 | txreq -req GET -url /req6 -hdr "X-my_hdr: on" |
3204 | rxresp |
3205 | expect resp.status == 403 |
3206 | + |
3207 | + txreq -req GET -url /req7 -hdr "X_my_hdr_with_lots_of_underscores: on" |
3208 | + rxresp |
3209 | + expect resp.status == 200 |
3210 | + |
3211 | + txreq -req GET -url /req8 -hdr "X_my_hdr-1: on" -hdr "X-my-hdr-2: on" |
3212 | + rxresp |
3213 | + expect resp.status == 200 |
3214 | + |
3215 | + txreq -req GET -url /req9 -hdr "X-my_hdr-1: on" -hdr "X-my_hdr-2: on" |
3216 | + rxresp |
3217 | + expect resp.status == 200 |
3218 | + |
3219 | + txreq -req GET -url /req10 -hdr "X-my-hdr-with-trailing-underscore_: on" |
3220 | + rxresp |
3221 | + expect resp.status == 200 |
3222 | } -run |
3223 | |
3224 | client c2 -connect ${h1_fe2_sock} { |
3225 | diff --git a/reg-tests/log/log_forward.vtc b/reg-tests/log/log_forward.vtc |
3226 | new file mode 100644 |
3227 | index 0000000..3977f4c |
3228 | --- /dev/null |
3229 | +++ b/reg-tests/log/log_forward.vtc |
3230 | @@ -0,0 +1,57 @@ |
3231 | +varnishtest "Test the TCP load-forward" |
3232 | +feature cmd "$HAPROXY_PROGRAM -cc 'version_atleast(2.3-dev1)'" |
3233 | +feature ignore_unknown_macro |
3234 | + |
3235 | +server s1 { |
3236 | + rxreq |
3237 | + txresp |
3238 | +} -repeat 500 -start |
3239 | + |
3240 | +syslog Slg1 -level info { |
3241 | + recv |
3242 | + expect ~ "[^:\\[ ]\\[${h1_pid}\\]: .* \"GET /client_c1 HTTP/1.1\"" |
3243 | +} -repeat 50 -start |
3244 | + |
3245 | +haproxy h1 -conf { |
3246 | + defaults |
3247 | + mode http |
3248 | + option httplog |
3249 | + timeout connect "${HAPROXY_TEST_TIMEOUT-5s}" |
3250 | + timeout client "${HAPROXY_TEST_TIMEOUT-5s}" |
3251 | + timeout server "${HAPROXY_TEST_TIMEOUT-5s}" |
3252 | + |
3253 | + frontend fe1 |
3254 | + bind "fd@${fe_1}" |
3255 | + log 127.0.0.1:1514 local0 |
3256 | +# log ${Slg1_addr}:${Slg1_port} local0 |
3257 | + default_backend be |
3258 | + |
3259 | + backend be |
3260 | + server app1 ${s1_addr}:${s1_port} |
3261 | + |
3262 | + ring myring |
3263 | + description "My local buffer" |
3264 | + format rfc5424 |
3265 | + maxlen 1200 |
3266 | + size 32764 |
3267 | + timeout connect 5s |
3268 | + timeout server 10s |
3269 | + # syslog tcp server |
3270 | + server mysyslogsrv 127.0.0.1:2514 |
3271 | + |
3272 | + log-forward syslog2tcp |
3273 | + dgram-bind 127.0.0.1:1514 |
3274 | + log ring@myring local0 # To TCP log |
3275 | + |
3276 | + log-forward syslog2local |
3277 | + bind 127.0.0.1:2514 |
3278 | + log ${Slg1_addr}:${Slg1_port} local0 # To VTest syslog |
3279 | +} -start |
3280 | + |
3281 | +client c1 -connect ${h1_fe_1_sock} { |
3282 | + txreq -url "/client_c1" |
3283 | + rxresp |
3284 | + expect resp.status == 200 |
3285 | +} -repeat 50 -start |
3286 | + |
3287 | +syslog Slg1 -wait |
3288 | diff --git a/reg-tests/mailers/healthcheckmail.vtc b/reg-tests/mailers/healthcheckmail.vtc |
3289 | index 43bf588..d36a0d3 100644 |
3290 | --- a/reg-tests/mailers/healthcheckmail.vtc |
3291 | +++ b/reg-tests/mailers/healthcheckmail.vtc |
3292 | @@ -5,7 +5,7 @@ feature ignore_unknown_macro |
3293 | |
3294 | syslog S1 -level notice { |
3295 | recv |
3296 | - expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be1/srv1 failed.+reason: Socket error.+info: \".+\".+check duration: [[:digit:]]+ms.+status: 0/1 DOWN." |
3297 | + expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be1/srv1 failed.+check duration: [[:digit:]]+ms.+status: 0/1 DOWN." |
3298 | recv info |
3299 | expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Result=SUCCESS Bytes=[[:digit:]]+" |
3300 | } -start |
3301 | diff --git a/reg-tests/ssl/log_forward_ssl.vtc b/reg-tests/ssl/log_forward_ssl.vtc |
3302 | new file mode 100644 |
3303 | index 0000000..6b7515b |
3304 | --- /dev/null |
3305 | +++ b/reg-tests/ssl/log_forward_ssl.vtc |
3306 | @@ -0,0 +1,60 @@ |
3307 | +varnishtest "Test the TCP+SSL load-forward" |
3308 | +feature cmd "$HAPROXY_PROGRAM -cc 'version_atleast(2.3-dev1)'" |
3309 | +feature cmd "$HAPROXY_PROGRAM -cc 'feature(OPENSSL)'" |
3310 | +feature ignore_unknown_macro |
3311 | + |
3312 | +server s1 { |
3313 | + rxreq |
3314 | + txresp |
3315 | +} -repeat 500 -start |
3316 | + |
3317 | +syslog Slg1 -level info { |
3318 | + recv |
3319 | + expect ~ "[^:\\[ ]\\[${h1_pid}\\]: .* \"GET /client_c1 HTTP/1.1\"" |
3320 | +} -repeat 50 -start |
3321 | + |
3322 | +haproxy h1 -conf { |
3323 | + global |
3324 | + insecure-fork-wanted |
3325 | + defaults |
3326 | + mode http |
3327 | + option httplog |
3328 | + timeout connect "${HAPROXY_TEST_TIMEOUT-5s}" |
3329 | + timeout client "${HAPROXY_TEST_TIMEOUT-5s}" |
3330 | + timeout server "${HAPROXY_TEST_TIMEOUT-5s}" |
3331 | + |
3332 | + frontend fe1 |
3333 | + bind "fd@${fe_1}" |
3334 | + log 127.0.0.1:1514 local0 |
3335 | +# log ${Slg1_addr}:${Slg1_port} local0 |
3336 | + default_backend be |
3337 | + |
3338 | + backend be |
3339 | + server app1 ${s1_addr}:${s1_port} |
3340 | + |
3341 | + ring myring |
3342 | + description "My local buffer" |
3343 | + format rfc5424 |
3344 | + maxlen 1200 |
3345 | + size 32764 |
3346 | + timeout connect 5s |
3347 | + timeout server 10s |
3348 | + # syslog tcp server |
3349 | + server mysyslogsrv 127.0.0.1:2514 ssl verify none |
3350 | + |
3351 | + log-forward syslog2tcp |
3352 | + dgram-bind 127.0.0.1:1514 |
3353 | + log ring@myring local0 # To TCP log |
3354 | + |
3355 | + log-forward syslog2local |
3356 | + bind 127.0.0.1:2514 ssl crt ${testdir}/common.pem |
3357 | + log ${Slg1_addr}:${Slg1_port} local0 # To VTest syslog |
3358 | +} -start |
3359 | + |
3360 | +client c1 -connect ${h1_fe_1_sock} { |
3361 | + txreq -url "/client_c1" |
3362 | + rxresp |
3363 | + expect resp.status == 200 |
3364 | +} -repeat 50 -start |
3365 | + |
3366 | +syslog Slg1 -wait |
3367 | diff --git a/reg-tests/startup/automatic_maxconn.vtc b/reg-tests/startup/automatic_maxconn.vtc |
3368 | new file mode 100644 |
3369 | index 0000000..686a5c5 |
3370 | --- /dev/null |
3371 | +++ b/reg-tests/startup/automatic_maxconn.vtc |
3372 | @@ -0,0 +1,102 @@ |
3373 | +#REGTEST_TYPE=broken |
3374 | +#REQUIRE_VERSION=2.2 |
3375 | +#REQUIRE_OPTION=OPENSSL |
3376 | + |
3377 | +# Check the maxconn computation with the -m parameter |
3378 | +# Broken because it can't work with ASAN. |
3379 | + |
3380 | +varnishtest "Automatic maxconn computation" |
3381 | + |
3382 | + |
3383 | +feature ignore_unknown_macro |
3384 | + |
3385 | +server s1 { |
3386 | + rxreq |
3387 | + txresp |
3388 | +} -start |
3389 | + |
3390 | + |
3391 | +haproxy h1 -arg "-m 1024" -conf { |
3392 | +} -start |
3393 | + |
3394 | +haproxy h1 -cli { |
3395 | + send "show info" |
3396 | + expect ~ ".*Maxconn: 29000\n.*" |
3397 | +} |
3398 | + |
3399 | +haproxy h2 -arg "-m 384" -conf { |
3400 | +} -start |
3401 | + |
3402 | +haproxy h2 -cli { |
3403 | + send "show info" |
3404 | + expect ~ ".*Maxconn: 10000\n.*" |
3405 | +} |
3406 | + |
3407 | +haproxy h3 -arg "-m 256" -conf { |
3408 | +} -start |
3409 | + |
3410 | +haproxy h3 -cli { |
3411 | + send "show info" |
3412 | + expect ~ ".*Maxconn: 7300\n.*" |
3413 | +} |
3414 | + |
3415 | +# 1 SSL front but no back |
3416 | + |
3417 | +haproxy h4 -arg "-m 256" -conf { |
3418 | + defaults |
3419 | + mode http |
3420 | + timeout connect 1s |
3421 | + timeout client 1s |
3422 | + timeout server 1s |
3423 | + |
3424 | + frontend fe1 |
3425 | + bind "fd@${fe1}" ssl crt ${testdir}/common.pem |
3426 | + |
3427 | +} -start |
3428 | + |
3429 | +haproxy h4 -cli { |
3430 | + send "show info" |
3431 | + expect ~ ".*Maxconn: 1900\n.*" |
3432 | +} |
3433 | + |
3434 | +# 1 SSL back but not front |
3435 | + |
3436 | +haproxy h5 -arg "-m 256" -conf { |
3437 | + defaults |
3438 | + mode http |
3439 | + timeout connect 1s |
3440 | + timeout client 1s |
3441 | + timeout server 1s |
3442 | + |
3443 | + listen li2 |
3444 | + bind "fd@${li2}" |
3445 | + server ssl "${s1_addr}:${s1_port}" ssl verify none |
3446 | + |
3447 | +} -start |
3448 | + |
3449 | +haproxy h5 -cli { |
3450 | + send "show info" |
3451 | + expect ~ ".*Maxconn: 1900\n.*" |
3452 | +} |
3453 | + |
3454 | + |
3455 | +# 1 SSL front and 1 back |
3456 | + |
3457 | +haproxy h6 -arg "-m 256" -conf { |
3458 | + defaults |
3459 | + mode http |
3460 | + timeout connect 1s |
3461 | + timeout client 1s |
3462 | + timeout server 1s |
3463 | + |
3464 | + listen li3 |
3465 | + bind "fd@${li3}" ssl crt ${testdir}/common.pem |
3466 | + server ssl "${s1_addr}:${s1_port}" ssl verify none |
3467 | + |
3468 | +} -start |
3469 | + |
3470 | +haproxy h6 -cli { |
3471 | + send "show info" |
3472 | + expect ~ ".*Maxconn: 1700\n.*" |
3473 | +} |
3474 | + |
3475 | diff --git a/reg-tests/startup/common.pem b/reg-tests/startup/common.pem |
3476 | new file mode 100644 |
3477 | index 0000000..206e417 |
3478 | --- /dev/null |
3479 | +++ b/reg-tests/startup/common.pem |
3480 | @@ -0,0 +1,117 @@ |
3481 | +-----BEGIN RSA PRIVATE KEY----- |
3482 | +MIIEpAIBAAKCAQEAnb0BDF7FsqzslakNg7u/n/JQkq6nheuKwvyTqECfpc9y7uSB |
3483 | +e/vrEFqBaDSLQagJxuZdL5geFeVtRbdAoB97N1/LZa6vecjjgGSP0Aag/gS/ocnM |
3484 | +RIyvlVWWT9MrD46OG3qZY1ORU1ltrVL0NKttJP8xME7j3bTwIDElx/hNI0n7L+yS |
3485 | +kAe2xb/7CbZRfoOhjTVAcGv4aSLVc/Hi8k6VkIzdOEtH6TcghXmuGcuqvLNH9Buo |
3486 | +syngKTcQ8zg6J+e64aVvC+e7vi94uil9Qu+JHm0pkDzAZ2WluNsuXlrJToPirWyj |
3487 | +6/YdN6xgSI1hbZkBmUPAebgYuxBt6huvfyQd3wIDAQABAoIBABojc8UE/2W4WgwC |
3488 | +04Z82ig7Ezb7Ui9S9M+S4zUCYHItijIkE4DkIfO3y7Hk4x6iJdyb191HK9UdC5p9 |
3489 | +32upS9XFPgM/izx3GZvxDhO+xXbSep7ovbyuQ3pPkHTx3TTavpm3GyvmcTKKoy4R |
3490 | +jP4dWhzDXPdQW1ol3ZS4EDau4rlyClY6oi1mq9aBEX3MqVjB/nO7s2AbdgclAgP2 |
3491 | +OZMhTzWYR1k5tYySHCXh3ggGMCikyvHU0+SsGyrstYzP1VYi/n3f0VgqW/5ZjG8x |
3492 | +6SHpe04unErPF3HuSun2ZMCFdBxaTFZ8FENb8evrSXe3nQOc9W21RQdRRrNNUbjl |
3493 | +JYI4veECgYEA0ATYKMS1VCUYRZoQ49b5GTg7avUYqfW4bEo4fSfBue8NrnKR3Wu8 |
3494 | +PPBiCTuIYq1vSF+60B7Vu+hW0A8OuQ2UuMxLpYcQ7lKfNad/+yAfoWWafIqCqNU9 |
3495 | +at0QMdbW6A69d6jZt7OrXtleBsphCnN58jTz4ch4PIa2Oyq46NUXCvUCgYEAwh8t |
3496 | +G6BOHOs3yRNI2s9Y9EEfwoil2uIKrZhqiL3AwdIpu5uNIMuPnbaEpXvRX6jv/qtL |
3497 | +321i8vZLc31aM7zfxQ6B4ReQFJfYC80FJsWvcLwT9hB9mTJpLS4sIu5tzQc87O6w |
3498 | +RtjFMom+5ns5hfPB4Eccy0EtbQWVY4nCzUeO6QMCgYBSvqqRRPXwG7VU8lznlHqP |
3499 | +upuABzChYrnScY+Y0TixUlL54l79Wb6N6vzEOWceAWkzu8iewrU4QspNhr/PgoR3 |
3500 | +IeSxWlG0yy7Dc/ZnmTabx8O06I/iwrfkizzG5nOj6UEamRLJjPGNEB/jyZriQl7u |
3501 | +pnugg1K4mMliLbNSAnlhBQKBgQCmYepbv260Qrex1KGhSg9Ia3k5V74weYYFfJnz |
3502 | +UhChD+1NK+ourcsOtp3C6PlwMHBjq5aAjlU9QfUxq8NgjQaO8/xGXdfUjsFSfAtq |
3503 | +TA4vZkUFpuTAJgEYBHc4CXx7OzTxLzRPxQRgaMgC7KNFOMR34vu/CsJQq3R7uFwL |
3504 | +bsYC2QKBgQCtEmg1uDZVdByX9zyUMuRxz5Tq/vDcp+A5lJj2mha1+bUMaKX2+lxQ |
3505 | +vPxY55Vaw/ukWkJirRrpGv6IytBn0dLAFSlKZworZGBaxsm8OGTFJ5Oe9+kZTjI9 |
3506 | +hvjpClOA1otbmj2F2uZAbuIjxQGDNUkLoifN5yDYCC8JPujHuHmULw== |
3507 | +-----END RSA PRIVATE KEY----- |
3508 | +-----BEGIN CERTIFICATE----- |
3509 | +MIIGeTCCBGGgAwIBAgIBAjANBgkqhkiG9w0BAQsFADB+MQswCQYDVQQGEwJGUjEW |
3510 | +MBQGA1UECBMNSWxlLWRlLUZyYW5jZTEOMAwGA1UEBxMFUGFyaXMxEDAOBgNVBAoT |
3511 | +B296b24uaW8xFTATBgNVBAMTDE96b24gVGVzdCBDQTEeMBwGCSqGSIb3DQEJARYP |
3512 | +c3VwcG9ydEBvem9uLmlvMB4XDTE2MDExNzIzMDIzOFoXDTE4MDExNjIzMDIzOFow |
3513 | +gb4xCzAJBgNVBAYTAkZSMRYwFAYDVQQIEw1JbGUtZGUtRnJhbmNlMRowGAYDVQQH |
3514 | +ExFOZXVpbGx5LXN1ci1TZWluZTEYMBYGA1UEChMPVE9BRCBDb25zdWx0aW5nMRcw |
3515 | +FQYDVQQLEw5lUGFyYXBoZXIgVGVhbTEWMBQGA1UEAxMNd3d3LnRlc3QxLmNvbTEw |
3516 | +MC4GCSqGSIb3DQEJARYhYXJuYXVsdC5taWNoZWxAdG9hZC1jb25zdWx0aW5nLmZy |
3517 | +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnb0BDF7FsqzslakNg7u/ |
3518 | +n/JQkq6nheuKwvyTqECfpc9y7uSBe/vrEFqBaDSLQagJxuZdL5geFeVtRbdAoB97 |
3519 | +N1/LZa6vecjjgGSP0Aag/gS/ocnMRIyvlVWWT9MrD46OG3qZY1ORU1ltrVL0NKtt |
3520 | +JP8xME7j3bTwIDElx/hNI0n7L+ySkAe2xb/7CbZRfoOhjTVAcGv4aSLVc/Hi8k6V |
3521 | +kIzdOEtH6TcghXmuGcuqvLNH9BuosyngKTcQ8zg6J+e64aVvC+e7vi94uil9Qu+J |
3522 | +Hm0pkDzAZ2WluNsuXlrJToPirWyj6/YdN6xgSI1hbZkBmUPAebgYuxBt6huvfyQd |
3523 | +3wIDAQABo4IBvzCCAbswCwYDVR0PBAQDAgOoMBMGA1UdJQQMMAoGCCsGAQUFBwMB |
3524 | +MB0GA1UdDgQWBBTIihFNVNgOseQnsWEcAQxAbIKE4TCBsgYDVR0jBIGqMIGngBRv |
3525 | +G9At9gzk2MW5Z7JVey1LtPIZ8KGBg6SBgDB+MQswCQYDVQQGEwJGUjEWMBQGA1UE |
3526 | +CBMNSWxlLWRlLUZyYW5jZTEOMAwGA1UEBxMFUGFyaXMxEDAOBgNVBAoTB296b24u |
3527 | +aW8xFTATBgNVBAMTDE96b24gVGVzdCBDQTEeMBwGCSqGSIb3DQEJARYPc3VwcG9y |
3528 | +dEBvem9uLmlvggkA15FtIaGcrk8wDAYDVR0TAQH/BAIwADAaBgNVHREEEzARgg9j |
3529 | +b21tb25OYW1lOmNvcHkwCQYDVR0SBAIwADBIBgNVHR8EQTA/MD2gO6A5hjdodHRw |
3530 | +Oi8vb3BlbnNzbGNhLnRvYWQtY29uc3VsdGluZy5jb20vb3BlbnZwbi9MYXRlc3Qu |
3531 | +Y3JsMBEGCWCGSAGG+EIBAQQEAwIGQDAxBglghkgBhvhCAQ0EJBYiVE9BRC1Db25z |
3532 | +dWx0aW5nIHNlcnZlciBjZXJ0aWZpY2F0ZTANBgkqhkiG9w0BAQsFAAOCAgEAewDa |
3533 | +9BukGNJMex8gsXmmdaczTr8yh9Uvw4NJcZS38I+26o//2g+d6i7wxcQg8hIm62Hj |
3534 | +0TblGU3+RsJo4uzcWxxA5YUYlVszbHNBRpQengEE5pjwHvoXVMNES6Bt8xP04+Vj |
3535 | +0qVnA8gUaDMk9lN5anK7tF/mbHOIJwHJZYCa2t3y95dIOVEXFwOIzzbSbaprjkLN |
3536 | +w0BgR5paJz7NZWNqo4sZHUUz94uH2bPEd01SqHO0dJwEVxadgxuPnD05I9gqGpGX |
3537 | +Zf3Rn7EQylvUtX9mpPaulQPXc3emefewLUSSAdnZrVikZK2J/B4lSi9FpUwl4iQH |
3538 | +pZoE0QLQHtB1SBKacnOAddGSTLSdFvpzjErjjWSpMukF0vutmrP86GG3xtshWVhI |
3539 | +u+yLfDJVm/pXfaeDtWMXpxIT/U1i0avpk5MZtFMRC0MTaxEWBTnnJm+/yiaAXQYg |
3540 | +E1ZIP0mkZkiUojIawTR7JTjHGhIraP9UVPNceVy0DLfETHEou3vhwBn7PFOz7piJ |
3541 | +wjp3A47DStJD4fapaX6B1fqM+n34CMD9ZAiJFgQEIQfObAWC9hyr4m+pqkp1Qfuw |
3542 | +vsAP/ZoS1CBirJfm3i+Gshh+VeH+TAmO/NBBYCfzBdgkNz4tJCkOc7CUT/NQTR/L |
3543 | +N2OskR/Fkge149RJi7hHvE3gk/mtGtNmHJPuQ+s= |
3544 | +-----END CERTIFICATE----- |
3545 | +-----BEGIN CERTIFICATE----- |
3546 | +MIIJazCCBVOgAwIBAgIUWHoc5e2FUECgyCvyVf8wCtt8gTYwDQYJKoZIhvcNAQEL |
3547 | +BQAwRTELMAkGA1UEBhMCRlIxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM |
3548 | +GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMDA4MDQxODU4MTZaFw0yMDA5 |
3549 | +MDMxODU4MTZaMEUxCzAJBgNVBAYTAkZSMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw |
3550 | +HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggQiMA0GCSqGSIb3DQEB |
3551 | +AQUAA4IEDwAwggQKAoIEAQDARiuHkhrnf38Md1nxGDSneJfwv/QksdNNMNTJBdjg |
3552 | +OVmaRCIAyz43oefTWDQ/TebbSwB+Lg9pud1zadGWhlZRhCgBPP8JDMhIKH4eXIRk |
3553 | +5IIa8WD08EwvSlqJL0r4gsMtVsxy7BZHAkka/2Ket9pyGt4kG5n75RFdc6BI80/8 |
3554 | +RwJt/MDxPrcVBAT7LnCluxQpyya9mZCabj7l+9a2yU2hgWS6QqfZJ133krkP/MMh |
3555 | +AEQkSoA4mmBwWk9yPqXmUqiOi7v6iLkIUEh5SgYVPRk9BtU/kDaUdSwuqRrpCZo4 |
3556 | +SsWZWFLxBmLHkSh+G+BWjCVYMQr2ye7e+VMT/20+5xAfq4fj9n5BsPcx3QcVuTof |
3557 | +RAc/Oygnt4MYnIcUb7zRFvCAvgpUHL7BnEn6nhyXjHJGqGDchsg8m9t3v/Y3ohq+ |
3558 | +qmrSzdeuylE1n3W5aWJlbFmyXegNP45MJ0xicesVrXEWF7YD/ir9mGJ8bQYr4blf |
3559 | +77PrbF02komC6AzVPKOJa0jR+eW1wErzYlkYgez6ylBWCiHJd1dhEHlK3h2rXdYa |
3560 | +Gnb45ILCLpEDjNEUrHifLLNXwqJpgZQsJU6BgMgk7ZgBfAKrCfTeg0rkCqCAPeVb |
3561 | +8eSLf7FBF7YBRJ5P6u8qXc4RtgEu607GaWV0gIMfyVBY52oV+OaNsEdFetrJnp3c |
3562 | +friG8vJ+7jdq6zjUCGgnfUIHoViJPh3JuFfhA3jT0gQDKW5PeI7dxhrNvlqdYfHI |
3563 | +fxX7Y1/J6cTQkqJ1cai2f0bwJIJiTAThNbG+zrtjJ7fZ3wJ4udyU/IKrwShqtmTb |
3564 | +1Ofj0tJDdwOH8i84vIySLUvR9aAb7ClFlnsx6rzwOxG90W7C0LA2M0EHm4FezJm/ |
3565 | +FfujnZwEWr1T9Wki6qE0MHCbdN/TTDws//EKkkE44FC+amL96w0IQl70vpE37j2A |
3566 | +zlDWvFFID95SIxfmpkwWDvXDKv6gr1GMLeysCl2fgpY05Xidw5cEo9/tEkuWn/dG |
3567 | +x/D9hnLBGeroA0251ES12jemqDjI2U0tfaeHakjwSsoWElf94Qmuh2iPZ+1zIxQs |
3568 | +7o6nAWN8X9hfsmrDTTHlww0TEfrjlbzG5Yh+0ZRxmejgiUyOCXck+eh/ZXMXvfWh |
3569 | +y3CorIIuWgkRjm80PYkdaRDJdZuyP6R7tXfTXNVzAiSQf0Qx9ru2KB2Fs/XZPamH |
3570 | +KjItAU5Q6msIVvaRMS0muQgV+b6hqSEBzqXqJfAlpVLHXr5FqK+U7EB9y02B6piB |
3571 | +tAmxqXP8OOCoQql6/vgIcrDFUOo6KtGBW36ef74XE3KCUVaIzVJZSIt6i/Vi0bZj |
3572 | +bAjsJUQ3qDlHdorv9TRVOhnC1GUz7SuYnpEOyiXmyx3LAgMBAAGjUzBRMB0GA1Ud |
3573 | +DgQWBBQ62csZcH/meQcENHhNbqz9LMzwjjAfBgNVHSMEGDAWgBQ62csZcH/meQcE |
3574 | +NHhNbqz9LMzwjjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IEAQBA |
3575 | +wLsGf3R1+/I2zQE+lsj7RasZtA/Cos92iEGDAPvFbx9e+roG8Gg8KBsEJu/HN0JH |
3576 | +lMMiQ8dDRHSBMvRBENL5/57oOOhmqc+1u5sazLuANhzAYPZG17Klib7YpEwWoXar |
3577 | +FDDiJYtCyLW0oNLpCswYopWK9GC0RJNucB0NFvOxehJ2sP2/fxGBQMB09L6mjKjd |
3578 | +4KsOzyd3dNf0VYS6jB+/1pcKSHKQUo9HRHB5FK04PsYHoh4AtmEHvmYQKcWWidgU |
3579 | +v26ftlH00ERzuW2juqBbz9mghlNRqXi0IyZ9b4tSj29dxW+WWFzo7j2zEPaD6z2W |
3580 | +DEHq7zvON+g+q6qLgWeszqMgJzjvWjMj00E/t06PoHPiz/cAnDKEqp+ZzxCIFrxj |
3581 | +/qneChpogDWyLbawhyyzbZvbirx5znOSbWjPZgydqaNEFViqbxwinBx4Xxabo6XN |
3582 | +TU020FuMWmgfbIcvtgjKgyKqc97l7JMNNm7LQV9+9W0U5zdIqQKLZ9MMrd2w3xh4 |
3583 | +MAB8NKnwzHReK0TWwUU9HSgFAGdEX6HnyZ3bQ13ijg+sNBRMEi0gBHaqZKDdyoft |
3584 | +B2u2uasSwioV48dbSIcHl+rTBKxiMh5XQ7ENnaGOJkjsIqTVzizqnPHU8eMBnSbb |
3585 | +dsXlamROYII44+j3Ku6OGt51w86eGk4VxI3tmaECcJKqTkwUFD8AcNDrkjtmLuxK |
3586 | +12yjnoM+u1cclfqQ5NOtRc6MJZ27jCobfBBhVdKVDp4X1WNyqGlbsU5adDAzknuI |
3587 | +GT7MJO7lGjkZX2n54BNPSfrSknYMOVYcZqL0Dbcrhx5IyEmg+iOlOu1HO1tdnZop |
3588 | +ej4vT+1V2w9Sa4Wo3UCo84jcm5v/4z7jCYh4BRQ60CFb7GLxZoqXIslcGSPool3n |
3589 | +jl8JWoaLXrJUPfZGXo1iAlayJ5EiMyZl4eB/TBUf6TMm8vLvsPiUT+CEsjLppOdS |
3590 | +eYppZAZ6H1JrJGs5kKBdOJHGn6Pkp5QsHIswOBd1HqHrBbYbZmDaDLRHduILWLrM |
3591 | +e0/IfDdeXB/bKfmZoEpT8xRiauw15p0AHLumiK7KISAehfgBqUnxx+YmgGoZ7EWX |
3592 | +KnMYAfCuC6oJ1DL0gp4Z9yMK1eu+GV1sLxPq9ZruEHW1R+H+4sGyiA5Gso2tgB6/ |
3593 | +XW//wxKclNp5LZR7hqfs/kGuh5asrJrnEbMwWn2+tr/LqfYtYh1D6nHfIXpT0o1d |
3594 | +rNy/HrsKnRDMWxjm03r4hCViuNVD3Zb9anAF/NSPDVu8ATM5JbJNrCYX4eipz6ZE |
3595 | +aQBkwIBkTPgtgP4r8v2G+uMYDw8nq7xh72FK107aeTTwc6MgU5jfeFNMr2XJisJd |
3596 | +lSem1ngKYQSEzjVsTE4c |
3597 | +-----END CERTIFICATE----- |
3598 | diff --git a/scripts/announce-release b/scripts/announce-release |
3599 | index 37e2ac4..c990821 100755 |
3600 | --- a/scripts/announce-release |
3601 | +++ b/scripts/announce-release |
3602 | @@ -210,20 +210,21 @@ else |
3603 | fi |
3604 | |
3605 | (echo "Please find the usual URLs below :" |
3606 | - echo " Site index : http://www.haproxy.org/" |
3607 | - echo " Documentation : http://docs.haproxy.org/" |
3608 | + echo " Site index : https://www.haproxy.org/" |
3609 | + echo " Documentation : https://docs.haproxy.org/" |
3610 | echo " Wiki : https://github.com/haproxy/wiki/wiki" |
3611 | - echo " Discourse : http://discourse.haproxy.org/" |
3612 | + echo " Discourse : https://discourse.haproxy.org/" |
3613 | echo " Slack channel : https://slack.haproxy.org/" |
3614 | echo " Issue tracker : https://github.com/haproxy/haproxy/issues" |
3615 | - echo " Sources : http://www.haproxy.org/download/${BRANCH}/src/" |
3616 | - echo " Git repository : http://git.haproxy.org/git/${gitdir}/" |
3617 | - echo " Git Web browsing : http://git.haproxy.org/?p=${gitdir}" |
3618 | - echo " Changelog : http://www.haproxy.org/download/${BRANCH}/src/CHANGELOG" |
3619 | - echo " Pending bugs : http://www.haproxy.org/l/pending-bugs" |
3620 | - echo " Reviewed bugs : http://www.haproxy.org/l/reviewed-bugs" |
3621 | - echo " Code reports : http://www.haproxy.org/l/code-reports" |
3622 | - echo " Latest builds : http://www.haproxy.org/l/dev-packages" |
3623 | + echo " Sources : https://www.haproxy.org/download/${BRANCH}/src/" |
3624 | + echo " Git repository : https://git.haproxy.org/git/${gitdir}/" |
3625 | + echo " Git Web browsing : https://git.haproxy.org/?p=${gitdir}" |
3626 | + echo " Changelog : https://www.haproxy.org/download/${BRANCH}/src/CHANGELOG" |
3627 | + echo " Dataplane API : https://github.com/haproxytech/dataplaneapi/releases/latest" |
3628 | + echo " Pending bugs : https://www.haproxy.org/l/pending-bugs" |
3629 | + echo " Reviewed bugs : https://www.haproxy.org/l/reviewed-bugs" |
3630 | + echo " Code reports : https://www.haproxy.org/l/code-reports" |
3631 | + echo " Latest builds : https://www.haproxy.org/l/dev-packages" |
3632 | ) >> "$OUTPUT" |
3633 | |
3634 | # sign |
3635 | diff --git a/src/backend.c b/src/backend.c |
3636 | index 6f2cc05..64780e4 100644 |
3637 | --- a/src/backend.c |
3638 | +++ b/src/backend.c |
3639 | @@ -2326,7 +2326,6 @@ void back_handle_st_cer(struct stream *s) |
3640 | |
3641 | /* only wait when we're retrying on the same server */ |
3642 | if ((si->state == SI_ST_ASS || |
3643 | - (s->be->lbprm.algo & BE_LB_KIND) != BE_LB_KIND_RR || |
3644 | (s->be->srv_act <= 1)) && !reused) { |
3645 | si->state = SI_ST_TAR; |
3646 | si->exp = tick_add(now_ms, MS_TO_TICKS(delay)); |
3647 | diff --git a/src/cache.c b/src/cache.c |
3648 | index ad4e715..ecf62fb 100644 |
3649 | --- a/src/cache.c |
3650 | +++ b/src/cache.c |
3651 | @@ -136,7 +136,7 @@ struct cache_st { |
3652 | struct cache_entry { |
3653 | unsigned int complete; /* An entry won't be valid until complete is not null. */ |
3654 | unsigned int latest_validation; /* latest validation date */ |
3655 | - unsigned int expire; /* expiration date */ |
3656 | + unsigned int expire; /* expiration date (wall clock time) */ |
3657 | unsigned int age; /* Origin server "Age" header value */ |
3658 | |
3659 | struct eb32_node eb; /* ebtree node used to hold the cache object */ |
3660 | @@ -188,7 +188,7 @@ struct cache_entry *entry_exist(struct cache *cache, char *hash) |
3661 | if (memcmp(entry->hash, hash, sizeof(entry->hash))) |
3662 | return NULL; |
3663 | |
3664 | - if (entry->expire > now.tv_sec) { |
3665 | + if (entry->expire > date.tv_sec) { |
3666 | return entry; |
3667 | } else { |
3668 | delete_entry(entry); |
3669 | @@ -249,7 +249,7 @@ struct cache_entry *secondary_entry_exist(struct cache *cache, struct cache_entr |
3670 | * when we find them. Calling delete_entry would be too costly |
3671 | * so we simply call eb32_delete. The secondary_entry count will |
3672 | * be updated when we try to insert a new entry to this list. */ |
3673 | - if (entry->expire <= now.tv_sec) { |
3674 | + if (entry->expire <= date.tv_sec) { |
3675 | eb32_delete(&entry->eb); |
3676 | entry->eb.key = 0; |
3677 | } |
3678 | @@ -258,7 +258,7 @@ struct cache_entry *secondary_entry_exist(struct cache *cache, struct cache_entr |
3679 | } |
3680 | |
3681 | /* Expired entry */ |
3682 | - if (entry && entry->expire <= now.tv_sec) { |
3683 | + if (entry && entry->expire <= date.tv_sec) { |
3684 | eb32_delete(&entry->eb); |
3685 | entry->eb.key = 0; |
3686 | entry = NULL; |
3687 | @@ -283,7 +283,7 @@ static unsigned int clear_expired_duplicates(struct eb32_node **dup_tail) |
3688 | while (prev) { |
3689 | entry = container_of(prev, struct cache_entry, eb); |
3690 | prev = eb32_prev_dup(prev); |
3691 | - if (entry->expire <= now.tv_sec) { |
3692 | + if (entry->expire <= date.tv_sec) { |
3693 | eb32_delete(&entry->eb); |
3694 | entry->eb.key = 0; |
3695 | } |
3696 | @@ -315,7 +315,7 @@ static struct eb32_node *insert_entry(struct cache *cache, struct cache_entry *n |
3697 | struct eb32_node *prev = NULL; |
3698 | struct cache_entry *entry = NULL; |
3699 | unsigned int entry_count = 0; |
3700 | - unsigned int last_clear_ts = now.tv_sec; |
3701 | + unsigned int last_clear_ts = date.tv_sec; |
3702 | |
3703 | struct eb32_node *node = eb32_insert(&cache->entries, &new_entry->eb); |
3704 | |
3705 | @@ -338,7 +338,7 @@ static struct eb32_node *insert_entry(struct cache *cache, struct cache_entry *n |
3706 | * space. In order to avoid going over the same list too |
3707 | * often, we first check the timestamp of the last check |
3708 | * performed. */ |
3709 | - if (last_clear_ts == now.tv_sec) { |
3710 | + if (last_clear_ts == date.tv_sec) { |
3711 | /* Too many entries for this primary key, clear the |
3712 | * one that was inserted. */ |
3713 | eb32_delete(node); |
3714 | @@ -351,7 +351,7 @@ static struct eb32_node *insert_entry(struct cache *cache, struct cache_entry *n |
3715 | /* Still too many entries for this primary key, delete |
3716 | * the newly inserted one. */ |
3717 | entry = container_of(prev, struct cache_entry, eb); |
3718 | - entry->last_clear_ts = now.tv_sec; |
3719 | + entry->last_clear_ts = date.tv_sec; |
3720 | eb32_delete(node); |
3721 | node->key = 0; |
3722 | return NULL; |
3723 | @@ -811,8 +811,8 @@ int http_calc_maxage(struct stream *s, struct cache *cache, int *true_maxage) |
3724 | /* A request having an expiring date earlier |
3725 | * than the current date should be considered as |
3726 | * stale. */ |
3727 | - expires = (expires_val >= now.tv_sec) ? |
3728 | - (expires_val - now.tv_sec) : 0; |
3729 | + expires = (expires_val >= date.tv_sec) ? |
3730 | + (expires_val - date.tv_sec) : 0; |
3731 | } |
3732 | else { |
3733 | /* Following RFC 7234#5.3, an invalid date |
3734 | @@ -886,7 +886,7 @@ static time_t get_last_modified_time(struct htx *htx) |
3735 | /* Fallback on the current time if no "Last-Modified" or "Date" header |
3736 | * was found. */ |
3737 | if (!last_modified) |
3738 | - last_modified = now.tv_sec; |
3739 | + last_modified = date.tv_sec; |
3740 | |
3741 | return last_modified; |
3742 | } |
3743 | @@ -1120,7 +1120,7 @@ enum act_return http_action_store_cache(struct act_rule *rule, struct proxy *px, |
3744 | * is set by the end of this function (in case of concurrent accesses to |
3745 | * the same resource). This way the second access will find an existing |
3746 | * but not yet usable entry in the tree and will avoid storing its data. */ |
3747 | - object->expire = now.tv_sec + 2; |
3748 | + object->expire = date.tv_sec + 2; |
3749 | |
3750 | memcpy(object->hash, txn->cache_hash, sizeof(object->hash)); |
3751 | if (vary_signature) |
3752 | @@ -1224,8 +1224,8 @@ enum act_return http_action_store_cache(struct act_rule *rule, struct proxy *px, |
3753 | if (cache_ctx) { |
3754 | cache_ctx->first_block = first; |
3755 | /* store latest value and expiration time */ |
3756 | - object->latest_validation = now.tv_sec; |
3757 | - object->expire = now.tv_sec + effective_maxage; |
3758 | + object->latest_validation = date.tv_sec; |
3759 | + object->expire = date.tv_sec + effective_maxage; |
3760 | return ACT_RET_CONT; |
3761 | } |
3762 | |
3763 | @@ -1416,7 +1416,7 @@ static int htx_cache_add_age_hdr(struct appctx *appctx, struct htx *htx) |
3764 | char *end; |
3765 | |
3766 | chunk_reset(&trash); |
3767 | - age = MAX(0, (int)(now.tv_sec - cache_ptr->latest_validation)) + cache_ptr->age; |
3768 | + age = MAX(0, (int)(date.tv_sec - cache_ptr->latest_validation)) + cache_ptr->age; |
3769 | if (unlikely(age > CACHE_ENTRY_MAX_AGE)) |
3770 | age = CACHE_ENTRY_MAX_AGE; |
3771 | end = ultoa_o(age, b_head(&trash), b_size(&trash)); |
3772 | @@ -2602,13 +2602,13 @@ static int cli_io_handler_show_cache(struct appctx *appctx) |
3773 | entry = container_of(node, struct cache_entry, eb); |
3774 | next_key = node->key + 1; |
3775 | |
3776 | - if (entry->expire > now.tv_sec) { |
3777 | + if (entry->expire > date.tv_sec) { |
3778 | chunk_printf(&trash, "%p hash:%u vary:0x", entry, read_u32(entry->hash)); |
3779 | for (i = 0; i < HTTP_CACHE_SEC_KEY_LEN; ++i) |
3780 | chunk_appendf(&trash, "%02x", (unsigned char)entry->secondary_key[i]); |
3781 | chunk_appendf(&trash, " size:%u (%u blocks), refcount:%u, expire:%d\n", |
3782 | block_ptr(entry)->len, block_ptr(entry)->block_count, |
3783 | - block_ptr(entry)->refcount, entry->expire - (int)now.tv_sec); |
3784 | + block_ptr(entry)->refcount, entry->expire - (int)date.tv_sec); |
3785 | } else { |
3786 | /* time to remove that one */ |
3787 | delete_entry(entry); |
3788 | diff --git a/src/cfgparse-listen.c b/src/cfgparse-listen.c |
3789 | index 4603376..35bd498 100644 |
3790 | --- a/src/cfgparse-listen.c |
3791 | +++ b/src/cfgparse-listen.c |
3792 | @@ -292,6 +292,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm) |
3793 | curr_defproxy = last_defproxy; |
3794 | |
3795 | if (strcmp(args[arg], "from") == 0) { |
3796 | + struct ebpt_node *next_by_name; |
3797 | + |
3798 | curr_defproxy = proxy_find_by_name(args[arg+1], PR_CAP_DEF, 0); |
3799 | |
3800 | if (!curr_defproxy) { |
3801 | @@ -300,8 +302,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm) |
3802 | goto out; |
3803 | } |
3804 | |
3805 | - if (ebpt_next_dup(&curr_defproxy->conf.by_name)) { |
3806 | - struct proxy *px2 = container_of(ebpt_next_dup(&curr_defproxy->conf.by_name), struct proxy, conf.by_name); |
3807 | + if ((next_by_name = ebpt_next_dup(&curr_defproxy->conf.by_name))) { |
3808 | + struct proxy *px2 = container_of(next_by_name, struct proxy, conf.by_name); |
3809 | |
3810 | ha_alert("parsing [%s:%d] : ambiguous defaults section name '%s' referenced by %s '%s' exists at least at %s:%d and %s:%d.\n", |
3811 | file, linenum, args[arg+1], proxy_cap_str(rc), name, |
3812 | diff --git a/src/cfgparse-ssl.c b/src/cfgparse-ssl.c |
3813 | index 654b020..fcd0416 100644 |
3814 | --- a/src/cfgparse-ssl.c |
3815 | +++ b/src/cfgparse-ssl.c |
3816 | @@ -758,7 +758,7 @@ static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, str |
3817 | { |
3818 | int code; |
3819 | char *p = args[cur_arg + 1]; |
3820 | - unsigned long long *ignerr = &conf->crt_ignerr; |
3821 | + unsigned long long *ignerr = conf->crt_ignerr_bitfield; |
3822 | |
3823 | if (!*p) { |
3824 | memprintf(err, "'%s' : missing error IDs list", args[cur_arg]); |
3825 | @@ -766,21 +766,21 @@ static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, str |
3826 | } |
3827 | |
3828 | if (strcmp(args[cur_arg], "ca-ignore-err") == 0) |
3829 | - ignerr = &conf->ca_ignerr; |
3830 | + ignerr = conf->ca_ignerr_bitfield; |
3831 | |
3832 | if (strcmp(p, "all") == 0) { |
3833 | - *ignerr = ~0ULL; |
3834 | + cert_ignerr_bitfield_set_all(ignerr); |
3835 | return 0; |
3836 | } |
3837 | |
3838 | while (p) { |
3839 | code = atoi(p); |
3840 | - if ((code <= 0) || (code > 63)) { |
3841 | - memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'", |
3842 | - args[cur_arg], code, args[cur_arg + 1]); |
3843 | + if ((code <= 0) || (code > SSL_MAX_VFY_ERROR_CODE)) { |
3844 | + memprintf(err, "'%s' : ID '%d' out of range (1..%d) in error IDs list '%s'", |
3845 | + args[cur_arg], code, SSL_MAX_VFY_ERROR_CODE, args[cur_arg + 1]); |
3846 | return ERR_ALERT | ERR_FATAL; |
3847 | } |
3848 | - *ignerr |= 1ULL << code; |
3849 | + cert_ignerr_bitfield_set(ignerr, code); |
3850 | p = strchr(p, ','); |
3851 | if (p) |
3852 | p++; |
3853 | diff --git a/src/cfgparse.c b/src/cfgparse.c |
3854 | index 4b42ec0..27bab1d 100644 |
3855 | --- a/src/cfgparse.c |
3856 | +++ b/src/cfgparse.c |
3857 | @@ -10,10 +10,10 @@ |
3858 | * |
3859 | */ |
3860 | |
3861 | -#ifdef USE_LIBCRYPT |
3862 | -/* This is to have crypt() defined on Linux */ |
3863 | +/* This is to have crypt() and sched_setaffinity() defined on Linux */ |
3864 | #define _GNU_SOURCE |
3865 | |
3866 | +#ifdef USE_LIBCRYPT |
3867 | #ifdef USE_CRYPT_H |
3868 | /* some platforms such as Solaris need this */ |
3869 | #include <crypt.h> |
3870 | @@ -29,6 +29,9 @@ |
3871 | #include <pwd.h> |
3872 | #include <grp.h> |
3873 | #include <errno.h> |
3874 | +#ifdef USE_CPU_AFFINITY |
3875 | +#include <sched.h> |
3876 | +#endif |
3877 | #include <sys/types.h> |
3878 | #include <sys/stat.h> |
3879 | #include <fcntl.h> |
3880 | @@ -62,6 +65,7 @@ |
3881 | #include <haproxy/lb_map.h> |
3882 | #include <haproxy/listener.h> |
3883 | #include <haproxy/log.h> |
3884 | +#include <haproxy/sink.h> |
3885 | #include <haproxy/mailers.h> |
3886 | #include <haproxy/namespace.h> |
3887 | #include <haproxy/obj_type-t.h> |
3888 | @@ -2630,6 +2634,7 @@ int check_config_validity() |
3889 | { |
3890 | int cfgerr = 0; |
3891 | struct proxy *curproxy = NULL; |
3892 | + struct proxy *init_proxies_list = NULL; |
3893 | struct stktable *t; |
3894 | struct server *newsrv = NULL; |
3895 | int err_code = 0; |
3896 | @@ -2707,7 +2712,11 @@ int check_config_validity() |
3897 | proxies_list = next; |
3898 | } |
3899 | |
3900 | - for (curproxy = proxies_list; curproxy; curproxy = curproxy->next) { |
3901 | + /* starting to initialize the main proxies list */ |
3902 | + init_proxies_list = proxies_list; |
3903 | + |
3904 | +init_proxies_list_stage1: |
3905 | + for (curproxy = init_proxies_list; curproxy; curproxy = curproxy->next) { |
3906 | struct switching_rule *rule; |
3907 | struct server_rule *srule; |
3908 | struct sticking_rule *mrule; |
3909 | @@ -2837,11 +2846,16 @@ int check_config_validity() |
3910 | case PR_MODE_CLI: |
3911 | cfgerr += proxy_cfg_ensure_no_http(curproxy); |
3912 | break; |
3913 | + |
3914 | case PR_MODE_SYSLOG: |
3915 | + /* this mode is initialized as the classic tcp proxy */ |
3916 | + cfgerr += proxy_cfg_ensure_no_http(curproxy); |
3917 | + break; |
3918 | + |
3919 | case PR_MODE_PEERS: |
3920 | case PR_MODES: |
3921 | /* should not happen, bug gcc warn missing switch statement */ |
3922 | - 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", |
3923 | + 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", |
3924 | proxy_type_str(curproxy), curproxy->id); |
3925 | cfgerr++; |
3926 | break; |
3927 | @@ -3966,6 +3980,24 @@ out_uri_auth_compat: |
3928 | } |
3929 | } |
3930 | |
3931 | + /* |
3932 | + * We have just initialized the main proxies list |
3933 | + * we must also configure the log-forward proxies list |
3934 | + */ |
3935 | + if (init_proxies_list == proxies_list) { |
3936 | + init_proxies_list = cfg_log_forward; |
3937 | + /* check if list is not null to avoid infinite loop */ |
3938 | + if (init_proxies_list) |
3939 | + goto init_proxies_list_stage1; |
3940 | + } |
3941 | + |
3942 | + if (init_proxies_list == cfg_log_forward) { |
3943 | + init_proxies_list = sink_proxies_list; |
3944 | + /* check if list is not null to avoid infinite loop */ |
3945 | + if (init_proxies_list) |
3946 | + goto init_proxies_list_stage1; |
3947 | + } |
3948 | + |
3949 | /***********************************************************/ |
3950 | /* At this point, target names have already been resolved. */ |
3951 | /***********************************************************/ |
3952 | @@ -4087,7 +4119,11 @@ out_uri_auth_compat: |
3953 | |
3954 | /* perform the final checks before creating tasks */ |
3955 | |
3956 | - for (curproxy = proxies_list; curproxy; curproxy = curproxy->next) { |
3957 | + /* starting to initialize the main proxies list */ |
3958 | + init_proxies_list = proxies_list; |
3959 | + |
3960 | +init_proxies_list_stage2: |
3961 | + for (curproxy = init_proxies_list; curproxy; curproxy = curproxy->next) { |
3962 | struct listener *listener; |
3963 | unsigned int next_id; |
3964 | |
3965 | @@ -4209,6 +4245,17 @@ out_uri_auth_compat: |
3966 | } |
3967 | |
3968 | /* |
3969 | + * We have just initialized the main proxies list |
3970 | + * we must also configure the log-forward proxies list |
3971 | + */ |
3972 | + if (init_proxies_list == proxies_list) { |
3973 | + init_proxies_list = cfg_log_forward; |
3974 | + /* check if list is not null to avoid infinite loop */ |
3975 | + if (init_proxies_list) |
3976 | + goto init_proxies_list_stage2; |
3977 | + } |
3978 | + |
3979 | + /* |
3980 | * Recount currently required checks. |
3981 | */ |
3982 | |
3983 | diff --git a/src/check.c b/src/check.c |
3984 | index 1a40b6f..2205063 100644 |
3985 | --- a/src/check.c |
3986 | +++ b/src/check.c |
3987 | @@ -1715,6 +1715,13 @@ static int init_srv_agent_check(struct server *srv) |
3988 | LIST_INSERT(srv->agent.tcpcheck_rules->list, &chk->list); |
3989 | } |
3990 | |
3991 | + /* <chk> is always defined here and it is a CONNECT action. If there is |
3992 | + * a preset variable, it means there is an agent string defined and data |
3993 | + * will be sent after the connect. |
3994 | + */ |
3995 | + if (!LIST_ISEMPTY(&srv->agent.tcpcheck_rules->preset_vars)) |
3996 | + chk->connect.options |= TCPCHK_OPT_HAS_DATA; |
3997 | + |
3998 | |
3999 | err = init_check(&srv->agent, PR_O2_TCPCHK_CHK); |
4000 | if (err) { |
4001 | diff --git a/src/dns.c b/src/dns.c |
4002 | index 1ef5e87..c4b2af0 100644 |
4003 | --- a/src/dns.c |
4004 | +++ b/src/dns.c |
4005 | @@ -1023,7 +1023,7 @@ struct dns_session *dns_session_new(struct dns_stream_server *dss) |
4006 | if (dss->maxconn && (dss->maxconn <= dss->cur_conns)) |
4007 | return NULL; |
4008 | |
4009 | - ds = pool_alloc(dns_session_pool); |
4010 | + ds = pool_zalloc(dns_session_pool); |
4011 | if (!ds) |
4012 | return NULL; |
4013 | |
4014 | diff --git a/src/ev_epoll.c b/src/ev_epoll.c |
4015 | index 330c38c..041d6d8 100644 |
4016 | --- a/src/ev_epoll.c |
4017 | +++ b/src/ev_epoll.c |
4018 | @@ -185,7 +185,7 @@ static void _do_poll(struct poller *p, int exp, int wake) |
4019 | |
4020 | thread_harmless_now(); |
4021 | |
4022 | - /* now let's wait for polled events */ |
4023 | + /* Now let's wait for polled events. */ |
4024 | wait_time = wake ? 0 : compute_poll_timeout(exp); |
4025 | tv_entering_poll(); |
4026 | activity_count_runtime(); |
4027 | @@ -201,7 +201,7 @@ static void _do_poll(struct poller *p, int exp, int wake) |
4028 | } |
4029 | if (timeout || !wait_time) |
4030 | break; |
4031 | - if (signal_queue_len || wake) |
4032 | + if (wake) |
4033 | break; |
4034 | if (tick_isset(exp) && tick_is_expired(exp, now_ms)) |
4035 | break; |
4036 | diff --git a/src/ev_evports.c b/src/ev_evports.c |
4037 | index 109e59c..e012e00 100644 |
4038 | --- a/src/ev_evports.c |
4039 | +++ b/src/ev_evports.c |
4040 | @@ -153,9 +153,7 @@ static void _do_poll(struct poller *p, int exp, int wake) |
4041 | |
4042 | thread_harmless_now(); |
4043 | |
4044 | - /* |
4045 | - * Determine how long to wait for events to materialise on the port. |
4046 | - */ |
4047 | + /* Now let's wait for polled events. */ |
4048 | wait_time = wake ? 0 : compute_poll_timeout(exp); |
4049 | tv_entering_poll(); |
4050 | activity_count_runtime(); |
4051 | @@ -195,7 +193,7 @@ static void _do_poll(struct poller *p, int exp, int wake) |
4052 | break; |
4053 | if (timeout || !wait_time) |
4054 | break; |
4055 | - if (signal_queue_len || wake) |
4056 | + if (wake) |
4057 | break; |
4058 | if (tick_isset(exp) && tick_is_expired(exp, now_ms)) |
4059 | break; |
4060 | diff --git a/src/ev_kqueue.c b/src/ev_kqueue.c |
4061 | index d51a833..0d81d67 100644 |
4062 | --- a/src/ev_kqueue.c |
4063 | +++ b/src/ev_kqueue.c |
4064 | @@ -141,7 +141,7 @@ static void _do_poll(struct poller *p, int exp, int wake) |
4065 | } |
4066 | fd_nbupdt = 0; |
4067 | |
4068 | - /* now let's wait for events */ |
4069 | + /* Now let's wait for polled events. */ |
4070 | wait_time = wake ? 0 : compute_poll_timeout(exp); |
4071 | fd = global.tune.maxpollevents; |
4072 | tv_entering_poll(); |
4073 | @@ -167,7 +167,7 @@ static void _do_poll(struct poller *p, int exp, int wake) |
4074 | } |
4075 | if (timeout || !wait_time) |
4076 | break; |
4077 | - if (signal_queue_len || wake) |
4078 | + if (wake) |
4079 | break; |
4080 | if (tick_isset(exp) && tick_is_expired(exp, now_ms)) |
4081 | break; |
4082 | diff --git a/src/ev_poll.c b/src/ev_poll.c |
4083 | index c30aadb..4d136a0 100644 |
4084 | --- a/src/ev_poll.c |
4085 | +++ b/src/ev_poll.c |
4086 | @@ -21,6 +21,7 @@ |
4087 | #include <haproxy/api.h> |
4088 | #include <haproxy/fd.h> |
4089 | #include <haproxy/global.h> |
4090 | +#include <haproxy/signal.h> |
4091 | #include <haproxy/ticks.h> |
4092 | #include <haproxy/time.h> |
4093 | |
4094 | @@ -198,7 +199,7 @@ static void _do_poll(struct poller *p, int exp, int wake) |
4095 | } |
4096 | } |
4097 | |
4098 | - /* now let's wait for events */ |
4099 | + /* Now let's wait for polled events. */ |
4100 | wait_time = wake ? 0 : compute_poll_timeout(exp); |
4101 | tv_entering_poll(); |
4102 | activity_count_runtime(); |
4103 | diff --git a/src/fcgi-app.c b/src/fcgi-app.c |
4104 | index 29a3602..8fca1e9 100644 |
4105 | --- a/src/fcgi-app.c |
4106 | +++ b/src/fcgi-app.c |
4107 | @@ -589,7 +589,7 @@ static int proxy_parse_use_fcgi_app(char **args, int section, struct proxy *curp |
4108 | struct fcgi_flt_conf *fcgi_conf = NULL; |
4109 | int retval = 0; |
4110 | |
4111 | - if (!(curpx->cap & PR_CAP_BE)) { |
4112 | + if ((curpx->cap & PR_CAP_DEF) || !(curpx->cap & PR_CAP_BE)) { |
4113 | memprintf(err, "'%s' only available in backend or listen section", args[0]); |
4114 | retval = -1; |
4115 | goto end; |
4116 | diff --git a/src/fcgi.c b/src/fcgi.c |
4117 | index 1c2543d..778ce9e 100644 |
4118 | --- a/src/fcgi.c |
4119 | +++ b/src/fcgi.c |
4120 | @@ -47,7 +47,7 @@ int fcgi_encode_record_hdr(struct buffer *out, const struct fcgi_header *h) |
4121 | out->area[len++] = ((h->len >> 8) & 0xff); |
4122 | out->area[len++] = (h->len & 0xff); |
4123 | out->area[len++] = h->padding; |
4124 | - len++; /* rsv */ |
4125 | + out->area[len++] = 0; /* rsv */ |
4126 | |
4127 | out->data = len; |
4128 | return 1; |
4129 | @@ -94,7 +94,11 @@ int fcgi_encode_begin_request(struct buffer *out, const struct fcgi_begin_reques |
4130 | out->area[len++] = ((r->role >> 8) & 0xff); |
4131 | out->area[len++] = (r->role & 0xff); |
4132 | out->area[len++] = r->flags; |
4133 | - len += 5; /* rsv */ |
4134 | + out->area[len++] = 0; /* rsv */ |
4135 | + out->area[len++] = 0; |
4136 | + out->area[len++] = 0; |
4137 | + out->area[len++] = 0; |
4138 | + out->area[len++] = 0; |
4139 | |
4140 | out->data = len; |
4141 | return 1; |
4142 | diff --git a/src/fd.c b/src/fd.c |
4143 | index b9c8ccc..3c9629f 100644 |
4144 | --- a/src/fd.c |
4145 | +++ b/src/fd.c |
4146 | @@ -206,7 +206,7 @@ lock_self: |
4147 | #ifdef HA_CAS_IS_8B |
4148 | unlikely(!_HA_ATOMIC_CAS(((uint64_t *)&_GET_NEXT(fd, off)), (uint64_t *)&cur_list.u64, next_list.u64)) |
4149 | #else |
4150 | - unlikely(!_HA_ATOMIC_DWCAS(((long *)&_GET_NEXT(fd, off)), (uint32_t *)&cur_list.u32, &next_list.u32)) |
4151 | + unlikely(!_HA_ATOMIC_DWCAS(((long *)&_GET_NEXT(fd, off)), (uint32_t *)&cur_list.u32, (const uint32_t *)&next_list.u32)) |
4152 | #endif |
4153 | ); |
4154 | next = cur_list.ent.next; |
4155 | @@ -666,9 +666,9 @@ static void deinit_pollers_per_thread() |
4156 | /* rd and wr are init at the same place, but only rd is init to -1, so |
4157 | we rely to rd to close. */ |
4158 | if (poller_rd_pipe > -1) { |
4159 | - close(poller_rd_pipe); |
4160 | + fd_delete(poller_rd_pipe); |
4161 | poller_rd_pipe = -1; |
4162 | - close(poller_wr_pipe[tid]); |
4163 | + fd_delete(poller_wr_pipe[tid]); |
4164 | poller_wr_pipe[tid] = -1; |
4165 | } |
4166 | } |
4167 | diff --git a/src/flt_http_comp.c b/src/flt_http_comp.c |
4168 | index a9c49f5..66eb601 100644 |
4169 | --- a/src/flt_http_comp.c |
4170 | +++ b/src/flt_http_comp.c |
4171 | @@ -304,23 +304,18 @@ set_compression_response_header(struct comp_state *st, struct stream *s, struct |
4172 | struct htx_sl *sl; |
4173 | struct http_hdr_ctx ctx; |
4174 | |
4175 | - /* |
4176 | - * Add Content-Encoding header when it's not identity encoding. |
4177 | - * RFC 2616 : Identity encoding: This content-coding is used only in the |
4178 | - * Accept-Encoding header, and SHOULD NOT be used in the Content-Encoding |
4179 | - * header. |
4180 | - */ |
4181 | - if (st->comp_algo->cfg_name_len != 8 || memcmp(st->comp_algo->cfg_name, "identity", 8) != 0) { |
4182 | - struct ist v = ist2(st->comp_algo->ua_name, st->comp_algo->ua_name_len); |
4183 | - |
4184 | - if (!http_add_header(htx, ist("Content-Encoding"), v)) |
4185 | - goto error; |
4186 | - } |
4187 | - |
4188 | sl = http_get_stline(htx); |
4189 | if (!sl) |
4190 | goto error; |
4191 | |
4192 | + /* add "Transfer-Encoding: chunked" header */ |
4193 | + if (!(msg->flags & HTTP_MSGF_TE_CHNK)) { |
4194 | + if (!http_add_header(htx, ist("Transfer-Encoding"), ist("chunked"))) |
4195 | + goto error; |
4196 | + msg->flags |= HTTP_MSGF_TE_CHNK; |
4197 | + sl->flags |= (HTX_SL_F_XFER_ENC|HTX_SL_F_CHNK); |
4198 | + } |
4199 | + |
4200 | /* remove Content-Length header */ |
4201 | if (msg->flags & HTTP_MSGF_CNT_LEN) { |
4202 | ctx.blk = NULL; |
4203 | @@ -330,14 +325,6 @@ set_compression_response_header(struct comp_state *st, struct stream *s, struct |
4204 | sl->flags &= ~HTX_SL_F_CLEN; |
4205 | } |
4206 | |
4207 | - /* add "Transfer-Encoding: chunked" header */ |
4208 | - if (!(msg->flags & HTTP_MSGF_TE_CHNK)) { |
4209 | - if (!http_add_header(htx, ist("Transfer-Encoding"), ist("chunked"))) |
4210 | - goto error; |
4211 | - msg->flags |= HTTP_MSGF_TE_CHNK; |
4212 | - sl->flags |= (HTX_SL_F_XFER_ENC|HTX_SL_F_CHNK); |
4213 | - } |
4214 | - |
4215 | /* convert "ETag" header to a weak ETag */ |
4216 | ctx.blk = NULL; |
4217 | if (http_find_header(htx, ist("ETag"), &ctx, 1)) { |
4218 | @@ -355,6 +342,19 @@ set_compression_response_header(struct comp_state *st, struct stream *s, struct |
4219 | if (!http_add_header(htx, ist("Vary"), ist("Accept-Encoding"))) |
4220 | goto error; |
4221 | |
4222 | + /* |
4223 | + * Add Content-Encoding header when it's not identity encoding. |
4224 | + * RFC 2616 : Identity encoding: This content-coding is used only in the |
4225 | + * Accept-Encoding header, and SHOULD NOT be used in the Content-Encoding |
4226 | + * header. |
4227 | + */ |
4228 | + if (st->comp_algo->cfg_name_len != 8 || memcmp(st->comp_algo->cfg_name, "identity", 8) != 0) { |
4229 | + struct ist v = ist2(st->comp_algo->ua_name, st->comp_algo->ua_name_len); |
4230 | + |
4231 | + if (!http_add_header(htx, ist("Content-Encoding"), v)) |
4232 | + goto error; |
4233 | + } |
4234 | + |
4235 | return 1; |
4236 | |
4237 | error: |
4238 | diff --git a/src/flt_spoe.c b/src/flt_spoe.c |
4239 | index cb7eed4..4826aa0 100644 |
4240 | --- a/src/flt_spoe.c |
4241 | +++ b/src/flt_spoe.c |
4242 | @@ -1259,7 +1259,7 @@ spoe_release_appctx(struct appctx *appctx) |
4243 | /* Destroy the task attached to this applet */ |
4244 | task_destroy(spoe_appctx->task); |
4245 | |
4246 | - /* Notify all waiting streams */ |
4247 | + /* Report an error to all streams in the appctx waiting queue */ |
4248 | list_for_each_entry_safe(ctx, back, &spoe_appctx->waiting_queue, list) { |
4249 | LIST_DELETE(&ctx->list); |
4250 | LIST_INIT(&ctx->list); |
4251 | @@ -1271,8 +1271,8 @@ spoe_release_appctx(struct appctx *appctx) |
4252 | task_wakeup(ctx->strm->task, TASK_WOKEN_MSG); |
4253 | } |
4254 | |
4255 | - /* If the applet was processing a fragmented frame, notify the |
4256 | - * corresponding stream. */ |
4257 | + /* If the applet was processing a fragmented frame, report an error to |
4258 | + * the corresponding stream. */ |
4259 | if (spoe_appctx->frag_ctx.ctx) { |
4260 | ctx = spoe_appctx->frag_ctx.ctx; |
4261 | ctx->spoe_appctx = NULL; |
4262 | @@ -1281,7 +1281,11 @@ spoe_release_appctx(struct appctx *appctx) |
4263 | task_wakeup(ctx->strm->task, TASK_WOKEN_MSG); |
4264 | } |
4265 | |
4266 | - if (!LIST_ISEMPTY(&agent->rt[tid].waiting_queue)) { |
4267 | + if (!LIST_ISEMPTY(&agent->rt[tid].applets)) { |
4268 | + /* If there are still some running applets, remove reference on |
4269 | + * the current one from streams in the async waiting queue. In |
4270 | + * async mode, the ACK may be received from another appctx. |
4271 | + */ |
4272 | list_for_each_entry_safe(ctx, back, &agent->rt[tid].waiting_queue, list) { |
4273 | if (ctx->spoe_appctx == spoe_appctx) |
4274 | ctx->spoe_appctx = NULL; |
4275 | @@ -1289,16 +1293,25 @@ spoe_release_appctx(struct appctx *appctx) |
4276 | goto end; |
4277 | } |
4278 | else { |
4279 | - /* It is the last running applet and the sending and waiting |
4280 | - * queues are not empty. Try to start a new one if HAproxy is |
4281 | - * not stopping. |
4282 | + /* It is the last running applet and the sending and async |
4283 | + * waiting queues are not empty. So try to start a new applet if |
4284 | + * HAproxy is not stopping. On success, we remove reference on |
4285 | + * the current appctx from streams in the async waiting queue. |
4286 | + * In async mode, the ACK may be received from another appctx. |
4287 | */ |
4288 | if (!stopping && |
4289 | (!LIST_ISEMPTY(&agent->rt[tid].sending_queue) || !LIST_ISEMPTY(&agent->rt[tid].waiting_queue)) && |
4290 | - spoe_create_appctx(agent->spoe_conf)) |
4291 | + spoe_create_appctx(agent->spoe_conf)) { |
4292 | + list_for_each_entry_safe(ctx, back, &agent->rt[tid].waiting_queue, list) { |
4293 | + if (ctx->spoe_appctx == spoe_appctx) |
4294 | + ctx->spoe_appctx = NULL; |
4295 | + } |
4296 | goto end; |
4297 | + } |
4298 | |
4299 | - /* otherwise, notify all waiting streams */ |
4300 | + /* Otherwise, report an error to all streams in the sending and |
4301 | + * async waiting queues. |
4302 | + */ |
4303 | list_for_each_entry_safe(ctx, back, &agent->rt[tid].sending_queue, list) { |
4304 | LIST_DELETE(&ctx->list); |
4305 | LIST_INIT(&ctx->list); |
4306 | diff --git a/src/h1.c b/src/h1.c |
4307 | index 3a6c1c3..73de48b 100644 |
4308 | --- a/src/h1.c |
4309 | +++ b/src/h1.c |
4310 | @@ -130,6 +130,50 @@ void h1_parse_xfer_enc_header(struct h1m *h1m, struct ist value) |
4311 | } |
4312 | } |
4313 | |
4314 | +/* Validate the authority and the host header value for CONNECT method. If there |
4315 | + * is hast header, its value is normalized. 0 is returned on success, -1 if the |
4316 | + * authority is invalid and -2 if the host is invalid. |
4317 | + */ |
4318 | +static int h1_validate_connect_authority(struct ist authority, struct ist *host_hdr) |
4319 | +{ |
4320 | + struct ist uri_host, uri_port, host, host_port; |
4321 | + |
4322 | + if (!isttest(authority)) |
4323 | + goto invalid_authority; |
4324 | + uri_host = authority; |
4325 | + uri_port = http_get_host_port(authority); |
4326 | + if (!isttest(uri_port)) |
4327 | + goto invalid_authority; |
4328 | + uri_host.len -= (istlen(uri_port) + 1); |
4329 | + |
4330 | + if (!host_hdr || !isttest(*host_hdr)) |
4331 | + goto end; |
4332 | + |
4333 | + /* Get the port of the host header value, if any */ |
4334 | + host = *host_hdr; |
4335 | + host_port = http_get_host_port(*host_hdr); |
4336 | + if (isttest(host_port)) { |
4337 | + host.len -= (istlen(host_port) + 1); |
4338 | + if (!isteqi(host, uri_host) || !isteq(host_port, uri_port)) |
4339 | + goto invalid_host; |
4340 | + if (http_is_default_port(IST_NULL, uri_port)) |
4341 | + *host_hdr = host; /* normalize */ |
4342 | + } |
4343 | + else { |
4344 | + if (!http_is_default_port(IST_NULL, uri_port) || !isteqi(host, uri_host)) |
4345 | + goto invalid_host; |
4346 | + } |
4347 | + |
4348 | + end: |
4349 | + return 0; |
4350 | + |
4351 | + invalid_authority: |
4352 | + return -1; |
4353 | + |
4354 | + invalid_host: |
4355 | + return -2; |
4356 | +} |
4357 | + |
4358 | /* Parse the Connection: header of an HTTP/1 request, looking for "close", |
4359 | * "keep-alive", and "upgrade" values, and updating h1m->flags according to |
4360 | * what was found there. Note that flags are only added, not removed, so the |
4361 | @@ -706,6 +750,10 @@ int h1_headers_to_hdr_list(char *start, const char *stop, |
4362 | |
4363 | if (likely(*ptr == ':')) { |
4364 | col = ptr - start; |
4365 | + if (col <= sol) { |
4366 | + state = H1_MSG_HDR_NAME; |
4367 | + goto http_msg_invalid; |
4368 | + } |
4369 | EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_hdr_l1_sp, http_msg_ood, state, H1_MSG_HDR_L1_SP); |
4370 | } |
4371 | |
4372 | @@ -868,22 +916,9 @@ int h1_headers_to_hdr_list(char *start, const char *stop, |
4373 | else if (isteqi(n, ist("upgrade"))) { |
4374 | h1_parse_upgrade_header(h1m, v); |
4375 | } |
4376 | - else if (!(h1m->flags & (H1_MF_HDRS_ONLY|H1_MF_RESP)) && isteqi(n, ist("host"))) { |
4377 | - if (host_idx == -1) { |
4378 | - struct ist authority; |
4379 | - |
4380 | - authority = http_get_authority(sl.rq.u, 1); |
4381 | - if (authority.len && !isteqi(v, authority)) { |
4382 | - if (h1m->err_pos < -1) { |
4383 | - state = H1_MSG_HDR_L2_LWS; |
4384 | - ptr = v.ptr; /* Set ptr on the error */ |
4385 | - goto http_msg_invalid; |
4386 | - } |
4387 | - if (h1m->err_pos == -1) /* capture the error pointer */ |
4388 | - h1m->err_pos = v.ptr - start + skip; /* >= 0 now */ |
4389 | - } |
4390 | + else if (!(h1m->flags & H1_MF_RESP) && isteqi(n, ist("host"))) { |
4391 | + if (host_idx == -1) |
4392 | host_idx = hdr_count; |
4393 | - } |
4394 | else { |
4395 | if (!isteqi(v, hdr[host_idx].v)) { |
4396 | state = H1_MSG_HDR_L2_LWS; |
4397 | @@ -934,6 +969,48 @@ int h1_headers_to_hdr_list(char *start, const char *stop, |
4398 | if (restarting) |
4399 | goto restart; |
4400 | |
4401 | + |
4402 | + if (!(h1m->flags & (H1_MF_HDRS_ONLY|H1_MF_RESP))) { |
4403 | + struct ist authority; |
4404 | + |
4405 | + authority = http_get_authority(sl.rq.u, 1); |
4406 | + if (sl.rq.meth == HTTP_METH_CONNECT) { |
4407 | + struct ist *host = ((host_idx != -1) ? &hdr[host_idx].v : NULL); |
4408 | + int ret; |
4409 | + |
4410 | + ret = h1_validate_connect_authority(authority, host); |
4411 | + if (ret < 0) { |
4412 | + if (h1m->err_pos < -1) { |
4413 | + state = H1_MSG_LAST_LF; |
4414 | + /* WT: gcc seems to see a path where sl.rq.u.ptr was used |
4415 | + * uninitialized, but it doesn't know that the function is |
4416 | + * called with initial states making this impossible. |
4417 | + */ |
4418 | + ALREADY_CHECKED(sl.rq.u.ptr); |
4419 | + ptr = ((ret == -1) ? sl.rq.u.ptr : host->ptr); /* Set ptr on the error */ |
4420 | + goto http_msg_invalid; |
4421 | + } |
4422 | + if (h1m->err_pos == -1) /* capture the error pointer */ |
4423 | + h1m->err_pos = ((ret == -1) ? sl.rq.u.ptr : host->ptr) - start + skip; /* >= 0 now */ |
4424 | + } |
4425 | + } |
4426 | + else if (host_idx != -1 && istlen(authority)) { |
4427 | + struct ist host = hdr[host_idx].v; |
4428 | + |
4429 | + /* For non-CONNECT method, the authority must match the host header value */ |
4430 | + if (!isteqi(authority, host)) { |
4431 | + if (h1m->err_pos < -1) { |
4432 | + state = H1_MSG_LAST_LF; |
4433 | + ptr = host.ptr; /* Set ptr on the error */ |
4434 | + goto http_msg_invalid; |
4435 | + } |
4436 | + if (h1m->err_pos == -1) /* capture the error pointer */ |
4437 | + h1m->err_pos = v.ptr - start + skip; /* >= 0 now */ |
4438 | + } |
4439 | + |
4440 | + } |
4441 | + } |
4442 | + |
4443 | state = H1_MSG_DATA; |
4444 | if (h1m->flags & H1_MF_XFER_ENC) { |
4445 | if (h1m->flags & H1_MF_CLEN) { |
4446 | diff --git a/src/h1_htx.c b/src/h1_htx.c |
4447 | index b6a91f2..650acba 100644 |
4448 | --- a/src/h1_htx.c |
4449 | +++ b/src/h1_htx.c |
4450 | @@ -279,6 +279,9 @@ static int h1_postparse_res_hdrs(struct h1m *h1m, union h1_sl *h1sl, struct htx |
4451 | goto output_full; |
4452 | } |
4453 | |
4454 | + if ((h1m->flags & (H1_MF_CONN_UPG|H1_MF_UPG_WEBSOCKET)) && code != 101) |
4455 | + h1m->flags &= ~(H1_MF_CONN_UPG|H1_MF_UPG_WEBSOCKET); |
4456 | + |
4457 | if (((h1m->flags & H1_MF_METH_CONNECT) && code >= 200 && code < 300) || code == 101) { |
4458 | h1m->flags &= ~(H1_MF_CLEN|H1_MF_CHNK); |
4459 | h1m->flags |= H1_MF_XFER_LEN; |
4460 | diff --git a/src/haproxy.c b/src/haproxy.c |
4461 | index b484195..2f85293 100644 |
4462 | --- a/src/haproxy.c |
4463 | +++ b/src/haproxy.c |
4464 | @@ -1,6 +1,6 @@ |
4465 | /* |
4466 | * HAProxy : High Availability-enabled HTTP/TCP proxy |
4467 | - * Copyright 2000-2022 Willy Tarreau <willy@haproxy.org>. |
4468 | + * Copyright 2000-2023 Willy Tarreau <willy@haproxy.org>. |
4469 | * |
4470 | * This program is free software; you can redistribute it and/or |
4471 | * modify it under the terms of the GNU General Public License |
4472 | @@ -2080,6 +2080,10 @@ static void init(int argc, char **argv) |
4473 | exit(1); |
4474 | } |
4475 | |
4476 | + /* set the default maxconn in the master, but let it be rewritable with -n */ |
4477 | + if (global.mode & MODE_MWORKER_WAIT) |
4478 | + global.maxconn = DEFAULT_MAXCONN; |
4479 | + |
4480 | if (cfg_maxconn > 0) |
4481 | global.maxconn = cfg_maxconn; |
4482 | |
4483 | @@ -2629,7 +2633,7 @@ void run_poll_loop() |
4484 | if (killed > 1) |
4485 | break; |
4486 | |
4487 | - /* expire immediately if events are pending */ |
4488 | + /* expire immediately if events or signals are pending */ |
4489 | wake = 1; |
4490 | if (thread_has_tasks()) |
4491 | activity[tid].wake_tasks++; |
4492 | @@ -2639,6 +2643,10 @@ void run_poll_loop() |
4493 | if (thread_has_tasks()) { |
4494 | activity[tid].wake_tasks++; |
4495 | _HA_ATOMIC_AND(&sleeping_thread_mask, ~tid_bit); |
4496 | + } else if (signal_queue_len) { |
4497 | + /* this check is required to avoid |
4498 | + * a race with wakeup on signals using wake_threads() */ |
4499 | + _HA_ATOMIC_AND(&sleeping_thread_mask, ~tid_bit); |
4500 | } else |
4501 | wake = 0; |
4502 | } |
4503 | diff --git a/src/hlua.c b/src/hlua.c |
4504 | index 0af3eb0..aea338f 100644 |
4505 | --- a/src/hlua.c |
4506 | +++ b/src/hlua.c |
4507 | @@ -738,7 +738,11 @@ __LJMP int hlua_lua2arg_check(lua_State *L, int first, struct arg *argp, |
4508 | break; |
4509 | |
4510 | case ARGT_TAB: |
4511 | - argp[idx].data.prx = p; |
4512 | + if (!p->table) { |
4513 | + msg = "Mandatory argument expected"; |
4514 | + goto error; |
4515 | + } |
4516 | + argp[idx].data.t = p->table; |
4517 | argp[idx].type = ARGT_TAB; |
4518 | argp[idx+1].type = ARGT_STOP; |
4519 | break; |
4520 | @@ -979,6 +983,7 @@ __LJMP int hlua_lua2arg_check(lua_State *L, int first, struct arg *argp, |
4521 | return 0; |
4522 | |
4523 | error: |
4524 | + argp[idx].type = ARGT_STOP; |
4525 | for (i = 0; i < idx; i++) { |
4526 | if (argp[i].type == ARGT_STR) |
4527 | chunk_destroy(&argp[i].data.str); |
4528 | @@ -4421,7 +4426,7 @@ __LJMP static int hlua_applet_http_getline_yield(lua_State *L, int status, lua_K |
4529 | /* The message was fully consumed and no more data are expected |
4530 | * (EOM flag set). |
4531 | */ |
4532 | - if (htx_is_empty(htx) && (htx->flags & HTX_FL_EOM)) |
4533 | + if (htx_is_empty(htx) && (req->flags & CF_EOI)) |
4534 | stop = 1; |
4535 | |
4536 | htx_to_buf(htx, &req->buf); |
4537 | @@ -4513,7 +4518,7 @@ __LJMP static int hlua_applet_http_recv_yield(lua_State *L, int status, lua_KCon |
4538 | /* The message was fully consumed and no more data are expected |
4539 | * (EOM flag set). |
4540 | */ |
4541 | - if (htx_is_empty(htx) && (htx->flags & HTX_FL_EOM)) |
4542 | + if (htx_is_empty(htx) && (req->flags & CF_EOI)) |
4543 | len = 0; |
4544 | |
4545 | htx_to_buf(htx, &req->buf); |
4546 | diff --git a/src/hlua_fcn.c b/src/hlua_fcn.c |
4547 | index 26aa509..010bd13 100644 |
4548 | --- a/src/hlua_fcn.c |
4549 | +++ b/src/hlua_fcn.c |
4550 | @@ -1305,6 +1305,7 @@ int hlua_proxy_pause(lua_State *L) |
4551 | struct proxy *px; |
4552 | |
4553 | px = hlua_check_proxy(L, 1); |
4554 | + /* safe to call without PROXY_LOCK - pause_proxy takes it */ |
4555 | pause_proxy(px); |
4556 | return 0; |
4557 | } |
4558 | @@ -1314,6 +1315,7 @@ int hlua_proxy_resume(lua_State *L) |
4559 | struct proxy *px; |
4560 | |
4561 | px = hlua_check_proxy(L, 1); |
4562 | + /* safe to call without PROXY_LOCK - resume_proxy takes it */ |
4563 | resume_proxy(px); |
4564 | return 0; |
4565 | } |
4566 | @@ -1323,6 +1325,7 @@ int hlua_proxy_stop(lua_State *L) |
4567 | struct proxy *px; |
4568 | |
4569 | px = hlua_check_proxy(L, 1); |
4570 | + /* safe to call without PROXY_LOCK - stop_proxy takes it */ |
4571 | stop_proxy(px); |
4572 | return 0; |
4573 | } |
4574 | diff --git a/src/hpack-dec.c b/src/hpack-dec.c |
4575 | index 4fa9bfd..ed39007 100644 |
4576 | --- a/src/hpack-dec.c |
4577 | +++ b/src/hpack-dec.c |
4578 | @@ -32,6 +32,7 @@ |
4579 | |
4580 | #include <import/ist.h> |
4581 | #include <haproxy/chunk.h> |
4582 | +#include <haproxy/global.h> |
4583 | #include <haproxy/h2.h> |
4584 | #include <haproxy/hpack-dec.h> |
4585 | #include <haproxy/hpack-huff.h> |
4586 | @@ -419,6 +420,15 @@ int hpack_decode_frame(struct hpack_dht *dht, const uint8_t *raw, uint32_t len, |
4587 | /* <name> and <value> are correctly filled here */ |
4588 | } |
4589 | |
4590 | + /* We must not accept empty header names (forbidden by the spec and used |
4591 | + * as a list termination). |
4592 | + */ |
4593 | + if (!name.len) { |
4594 | + hpack_debug_printf("##ERR@%d##\n", __LINE__); |
4595 | + ret = -HPACK_ERR_INVALID_ARGUMENT; |
4596 | + goto leave; |
4597 | + } |
4598 | + |
4599 | /* here's what we have here : |
4600 | * - name.len > 0 |
4601 | * - value is filled with either const data or data allocated from tmp |
4602 | diff --git a/src/http.c b/src/http.c |
4603 | index 0b00e47..c10b433 100644 |
4604 | --- a/src/http.c |
4605 | +++ b/src/http.c |
4606 | @@ -468,6 +468,38 @@ const char *http_get_reason(unsigned int status) |
4607 | } |
4608 | } |
4609 | |
4610 | +/* Returns the ist string corresponding to port part (without ':') in the host |
4611 | + * <host> or IST_NULL if not found. |
4612 | +*/ |
4613 | +struct ist http_get_host_port(const struct ist host) |
4614 | +{ |
4615 | + char *start, *end, *ptr; |
4616 | + |
4617 | + start = istptr(host); |
4618 | + end = istend(host); |
4619 | + for (ptr = end; ptr > start && isdigit((unsigned char)*--ptr);); |
4620 | + |
4621 | + /* no port found */ |
4622 | + if (likely(*ptr != ':' || ptr+1 == end || ptr == start)) |
4623 | + return IST_NULL; |
4624 | + |
4625 | + return istnext(ist2(ptr, end - ptr)); |
4626 | +} |
4627 | + |
4628 | + |
4629 | +/* Return non-zero if the port <port> is a default port. If the scheme <schm> is |
4630 | + * set, it is used to detect default ports (HTTP => 80 and HTTPS => 443) |
4631 | + * port. Otherwise, both are considered as default ports. |
4632 | + */ |
4633 | +int http_is_default_port(const struct ist schm, const struct ist port) |
4634 | +{ |
4635 | + if (!isttest(schm)) |
4636 | + return (isteq(port, ist("443")) || isteq(port, ist("80"))); |
4637 | + else |
4638 | + return (isteq(port, ist("443")) && isteqi(schm, ist("https://"))) || |
4639 | + (isteq(port, ist("80")) && isteqi(schm, ist("http://"))); |
4640 | +} |
4641 | + |
4642 | /* Returns non-zero if the scheme <schm> is syntactically correct according to |
4643 | * RFC3986#3.1, otherwise zero. It expects only the scheme and nothing else |
4644 | * (particularly not the following "://"). |
4645 | diff --git a/src/http_act.c b/src/http_act.c |
4646 | index f88c856..59e614f 100644 |
4647 | --- a/src/http_act.c |
4648 | +++ b/src/http_act.c |
4649 | @@ -1877,6 +1877,8 @@ static void release_http_redir(struct act_rule *rule) |
4650 | free(redir->cookie_str); |
4651 | list_for_each_entry_safe(lf, lfb, &redir->rdr_fmt, list) { |
4652 | LIST_DELETE(&lf->list); |
4653 | + release_sample_expr(lf->expr); |
4654 | + free(lf->arg); |
4655 | free(lf); |
4656 | } |
4657 | free(redir); |
4658 | diff --git a/src/http_ana.c b/src/http_ana.c |
4659 | index 4491ea1..2e2095b 100644 |
4660 | --- a/src/http_ana.c |
4661 | +++ b/src/http_ana.c |
4662 | @@ -938,9 +938,8 @@ int http_wait_for_request_body(struct stream *s, struct channel *req, int an_bit |
4663 | { |
4664 | struct session *sess = s->sess; |
4665 | struct http_txn *txn = s->txn; |
4666 | - struct http_msg *msg = &s->txn->req; |
4667 | |
4668 | - DBG_TRACE_ENTER(STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn, msg); |
4669 | + DBG_TRACE_ENTER(STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn, &s->txn->req); |
4670 | |
4671 | |
4672 | switch (http_wait_for_msg_body(s, req, s->be->timeout.httpreq, 0)) { |
4673 | @@ -998,7 +997,7 @@ int http_wait_for_request_body(struct stream *s, struct channel *req, int an_bit |
4674 | if (!(s->flags & SF_ERR_MASK)) |
4675 | s->flags |= SF_ERR_PRXCOND; |
4676 | if (!(s->flags & SF_FINST_MASK)) |
4677 | - s->flags |= (msg->msg_state < HTTP_MSG_DATA ? SF_FINST_R : SF_FINST_D); |
4678 | + s->flags |= SF_FINST_R; |
4679 | |
4680 | req->analysers &= AN_REQ_FLT_END; |
4681 | req->analyse_exp = TICK_ETERNITY; |
4682 | @@ -2655,17 +2654,21 @@ static enum rule_result http_req_restrict_header_names(struct stream *s, struct |
4683 | |
4684 | if (type == HTX_BLK_HDR) { |
4685 | struct ist n = htx_get_blk_name(htx, blk); |
4686 | - int i; |
4687 | + int i, end = istlen(n); |
4688 | |
4689 | - for (i = 0; i < istlen(n); i++) { |
4690 | + for (i = 0; i < end; i++) { |
4691 | if (!isalnum((unsigned char)n.ptr[i]) && n.ptr[i] != '-') { |
4692 | - /* Block the request or remove the header */ |
4693 | - if (px->options2 & PR_O2_RSTRICT_REQ_HDR_NAMES_BLK) |
4694 | - goto block; |
4695 | - blk = htx_remove_blk(htx, blk); |
4696 | - continue; |
4697 | + break; |
4698 | } |
4699 | } |
4700 | + |
4701 | + if (i < end) { |
4702 | + /* Disallowed character found - block the request or remove the header */ |
4703 | + if (px->options2 & PR_O2_RSTRICT_REQ_HDR_NAMES_BLK) |
4704 | + goto block; |
4705 | + blk = htx_remove_blk(htx, blk); |
4706 | + continue; |
4707 | + } |
4708 | } |
4709 | if (type == HTX_BLK_EOH) |
4710 | break; |
4711 | @@ -2778,6 +2781,7 @@ int http_res_set_status(unsigned int status, struct ist reason, struct stream *s |
4712 | |
4713 | if (!http_replace_res_status(htx, ist2(trash.area, trash.data), reason)) |
4714 | return -1; |
4715 | + s->txn->status = status; |
4716 | return 0; |
4717 | } |
4718 | |
4719 | @@ -4241,7 +4245,7 @@ enum rule_result http_wait_for_msg_body(struct stream *s, struct channel *chn, |
4720 | if (!(s->flags & SF_ERR_MASK)) |
4721 | s->flags |= SF_ERR_CLITO; |
4722 | if (!(s->flags & SF_FINST_MASK)) |
4723 | - s->flags |= SF_FINST_D; |
4724 | + s->flags |= SF_FINST_R; |
4725 | _HA_ATOMIC_INC(&sess->fe->fe_counters.failed_req); |
4726 | if (sess->listener && sess->listener->counters) |
4727 | _HA_ATOMIC_INC(&sess->listener->counters->failed_req); |
4728 | @@ -4254,7 +4258,7 @@ enum rule_result http_wait_for_msg_body(struct stream *s, struct channel *chn, |
4729 | if (!(s->flags & SF_ERR_MASK)) |
4730 | s->flags |= SF_ERR_SRVTO; |
4731 | if (!(s->flags & SF_FINST_MASK)) |
4732 | - s->flags |= SF_FINST_D; |
4733 | + s->flags |= SF_FINST_R; |
4734 | stream_inc_http_fail_ctr(s); |
4735 | http_reply_and_close(s, txn->status, http_error_message(s)); |
4736 | ret = HTTP_RULE_RES_ABRT; |
4737 | @@ -5205,8 +5209,10 @@ struct http_txn *http_create_txn(struct stream *s) |
4738 | |
4739 | txn->auth.method = HTTP_AUTH_UNKNOWN; |
4740 | |
4741 | - vars_init(&s->vars_txn, SCOPE_TXN); |
4742 | - vars_init(&s->vars_reqres, SCOPE_REQ); |
4743 | + /* here we don't want to re-initialize s->vars_txn and s->vars_reqres |
4744 | + * variable lists, because they were already initialized upon stream |
4745 | + * creation in stream_new(), and thus may already contain some variables |
4746 | + */ |
4747 | |
4748 | return txn; |
4749 | } |
4750 | diff --git a/src/http_fetch.c b/src/http_fetch.c |
4751 | index 3950eea..6678c85 100644 |
4752 | --- a/src/http_fetch.c |
4753 | +++ b/src/http_fetch.c |
4754 | @@ -222,7 +222,7 @@ struct htx *smp_prefetch_htx(struct sample *smp, struct channel *chn, struct che |
4755 | if (IS_HTX_STRM(s)) { |
4756 | htx = htxbuf(&chn->buf); |
4757 | |
4758 | - if (msg->msg_state == HTTP_MSG_ERROR || (htx->flags & HTX_FL_PARSING_ERROR)) |
4759 | + if (htx->flags & HTX_FL_PARSING_ERROR) |
4760 | return NULL; |
4761 | |
4762 | if (msg->msg_state < HTTP_MSG_BODY) { |
4763 | @@ -307,7 +307,7 @@ struct htx *smp_prefetch_htx(struct sample *smp, struct channel *chn, struct che |
4764 | if (txn->meth == HTTP_METH_GET || txn->meth == HTTP_METH_HEAD) |
4765 | s->flags |= SF_REDIRECTABLE; |
4766 | } |
4767 | - else |
4768 | + else if (txn->status == -1) |
4769 | txn->status = sl->info.res.status; |
4770 | if (sl->flags & HTX_SL_F_VER_11) |
4771 | msg->flags |= HTTP_MSGF_VER_11; |
4772 | @@ -330,20 +330,21 @@ static int smp_fetch_meth(const struct arg *args, struct sample *smp, const char |
4773 | { |
4774 | struct channel *chn = SMP_REQ_CHN(smp); |
4775 | struct http_txn *txn; |
4776 | - struct htx *htx; |
4777 | + struct htx *htx = NULL; |
4778 | int meth; |
4779 | |
4780 | txn = (smp->strm ? smp->strm->txn : NULL); |
4781 | if (!txn) |
4782 | return 0; |
4783 | |
4784 | - if (txn->meth == HTTP_METH_OTHER) { |
4785 | + meth = txn->meth; |
4786 | + if (meth == HTTP_METH_OTHER) { |
4787 | htx = smp_prefetch_htx(smp, chn, NULL, 1); |
4788 | if (!htx) |
4789 | return 0; |
4790 | + meth = txn->meth; |
4791 | } |
4792 | |
4793 | - meth = txn->meth; |
4794 | smp->data.type = SMP_T_METH; |
4795 | smp->data.u.meth.meth = meth; |
4796 | if (meth == HTTP_METH_OTHER) { |
4797 | diff --git a/src/http_htx.c b/src/http_htx.c |
4798 | index 6f5c1a1..60525bb 100644 |
4799 | --- a/src/http_htx.c |
4800 | +++ b/src/http_htx.c |
4801 | @@ -388,6 +388,9 @@ int http_replace_req_uri(struct htx *htx, const struct ist uri) |
4802 | goto fail; |
4803 | |
4804 | sl = http_get_stline(htx); |
4805 | + ALREADY_CHECKED(sl); /* the stline exists because http_replace_stline() succeded */ |
4806 | + sl->flags &= ~HTX_SL_F_NORMALIZED_URI; |
4807 | + |
4808 | if (!http_update_host(htx, sl, uri)) |
4809 | goto fail; |
4810 | |
4811 | @@ -918,7 +921,7 @@ int http_str_to_htx(struct buffer *buf, struct ist raw, char **errmsg) |
4812 | ret = h1_headers_to_hdr_list(raw.ptr, raw.ptr + raw.len, |
4813 | hdrs, sizeof(hdrs)/sizeof(hdrs[0]), &h1m, &h1sl); |
4814 | if (ret <= 0) { |
4815 | - memprintf(errmsg, "unabled to parse headers (error offset: %d)", h1m.err_pos); |
4816 | + memprintf(errmsg, "unable to parse headers (error offset: %d)", h1m.err_pos); |
4817 | goto error; |
4818 | } |
4819 | |
4820 | @@ -1565,6 +1568,7 @@ struct http_reply *http_parse_http_reply(const char **args, int *orig_arg, struc |
4821 | fd = -1; |
4822 | obj[objlen] = '\0'; |
4823 | reply->type = HTTP_REPLY_LOGFMT; |
4824 | + LIST_INIT(&reply->body.fmt); |
4825 | cur_arg++; |
4826 | } |
4827 | else if (strcmp(args[cur_arg], "lf-string") == 0) { |
4828 | @@ -1581,6 +1585,7 @@ struct http_reply *http_parse_http_reply(const char **args, int *orig_arg, struc |
4829 | obj = strdup(args[cur_arg]); |
4830 | objlen = strlen(args[cur_arg]); |
4831 | reply->type = HTTP_REPLY_LOGFMT; |
4832 | + LIST_INIT(&reply->body.fmt); |
4833 | cur_arg++; |
4834 | } |
4835 | else if (strcmp(args[cur_arg], "hdr") == 0) { |
4836 | @@ -1721,12 +1726,6 @@ struct http_reply *http_parse_http_reply(const char **args, int *orig_arg, struc |
4837 | return NULL; |
4838 | } |
4839 | |
4840 | -static int uri_is_default_port(const struct ist scheme, const struct ist port) |
4841 | -{ |
4842 | - return (isteq(port, ist("443")) && isteqi(scheme, ist("https://"))) || |
4843 | - (isteq(port, ist("80")) && isteqi(scheme, ist("http://"))); |
4844 | -} |
4845 | - |
4846 | /* Apply schemed-based normalization as described on rfc3986 on section 6.3.2. |
4847 | * Returns 0 if no error has been found else non-zero. |
4848 | * |
4849 | @@ -1741,7 +1740,6 @@ int http_scheme_based_normalize(struct htx *htx) |
4850 | struct http_hdr_ctx ctx; |
4851 | struct htx_sl *sl; |
4852 | struct ist uri, scheme, authority, host, port; |
4853 | - char *start, *end, *ptr; |
4854 | |
4855 | sl = http_get_stline(htx); |
4856 | |
4857 | @@ -1755,25 +1753,16 @@ int http_scheme_based_normalize(struct htx *htx) |
4858 | if (!isttest(scheme)) |
4859 | return 0; |
4860 | |
4861 | - /* Extract the port if present in authority. To properly support ipv6 |
4862 | - * hostnames, do a reverse search on the last ':' separator as long as |
4863 | - * digits are found. |
4864 | - */ |
4865 | - authority = http_get_authority(uri, 0); |
4866 | - start = istptr(authority); |
4867 | - end = istend(authority); |
4868 | - for (ptr = end; ptr > start && isdigit((unsigned char)*--ptr); ) |
4869 | - ; |
4870 | - |
4871 | - /* if no port found, no normalization to proceed */ |
4872 | - if (likely(*ptr != ':')) |
4873 | + /* Extract the port if present in authority */ |
4874 | + authority = http_get_authority(uri, 1); |
4875 | + port = http_get_host_port(authority); |
4876 | + if (!isttest(port)) { |
4877 | + /* if no port found, no normalization to proceed */ |
4878 | return 0; |
4879 | + } |
4880 | + host = isttrim(authority, istlen(authority) - istlen(port) - 1); |
4881 | |
4882 | - /* split host/port on the ':' separator found */ |
4883 | - host = ist2(start, ptr - start); |
4884 | - port = istnext(ist2(ptr, end - ptr)); |
4885 | - |
4886 | - if (istlen(port) && uri_is_default_port(scheme, port)) { |
4887 | + if (istlen(port) && http_is_default_port(scheme, port)) { |
4888 | /* reconstruct the uri with removal of the port */ |
4889 | struct buffer *temp = get_trash_chunk(); |
4890 | struct ist meth, vsn; |
4891 | diff --git a/src/listener.c b/src/listener.c |
4892 | index 0ffd0fe..67616f5 100644 |
4893 | --- a/src/listener.c |
4894 | +++ b/src/listener.c |
4895 | @@ -45,6 +45,7 @@ static struct bind_kw_list bind_keywords = { |
4896 | /* list of the temporarily limited listeners because of lack of resource */ |
4897 | static struct mt_list global_listener_queue = MT_LIST_HEAD_INIT(global_listener_queue); |
4898 | static struct task *global_listener_queue_task; |
4899 | +__decl_thread(static HA_RWLOCK_T global_listener_rwlock); |
4900 | |
4901 | /* listener status for stats */ |
4902 | const char* li_status_st[LI_STATE_COUNT] = { |
4903 | @@ -297,13 +298,14 @@ void enable_listener(struct listener *listener) |
4904 | |
4905 | /* |
4906 | * This function completely stops a listener. It will need to operate under the |
4907 | - * proxy's lock, the protocol's lock, and the listener's lock. The caller is |
4908 | - * responsible for indicating in lpx, lpr, lli whether the respective locks are |
4909 | - * already held (non-zero) or not (zero) so that the function picks the missing |
4910 | - * ones, in this order. The proxy's listeners count is updated and the proxy is |
4911 | + * It will need to operate under the proxy's lock and the protocol's lock. |
4912 | + * The caller is responsible for indicating in lpx, lpr whether the |
4913 | + * respective locks are already held (non-zero) or not (zero) so that the |
4914 | + * function picks the missing ones, in this order. |
4915 | + * The proxy's listeners count is updated and the proxy is |
4916 | * disabled and woken up after the last one is gone. |
4917 | */ |
4918 | -void stop_listener(struct listener *l, int lpx, int lpr, int lli) |
4919 | +void stop_listener(struct listener *l, int lpx, int lpr) |
4920 | { |
4921 | struct proxy *px = l->bind_conf->frontend; |
4922 | |
4923 | @@ -320,8 +322,7 @@ void stop_listener(struct listener *l, int lpx, int lpr, int lli) |
4924 | if (!lpr) |
4925 | HA_SPIN_LOCK(PROTO_LOCK, &proto_lock); |
4926 | |
4927 | - if (!lli) |
4928 | - HA_RWLOCK_WRLOCK(LISTENER_LOCK, &l->lock); |
4929 | + HA_RWLOCK_WRLOCK(LISTENER_LOCK, &l->lock); |
4930 | |
4931 | if (l->state > LI_INIT) { |
4932 | do_unbind_listener(l); |
4933 | @@ -332,8 +333,7 @@ void stop_listener(struct listener *l, int lpx, int lpr, int lli) |
4934 | proxy_cond_disable(px); |
4935 | } |
4936 | |
4937 | - if (!lli) |
4938 | - HA_RWLOCK_WRUNLOCK(LISTENER_LOCK, &l->lock); |
4939 | + HA_RWLOCK_WRUNLOCK(LISTENER_LOCK, &l->lock); |
4940 | |
4941 | if (!lpr) |
4942 | HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock); |
4943 | @@ -422,12 +422,18 @@ int default_resume_listener(struct listener *l) |
4944 | * closes upon SHUT_WR and refuses to rebind. So a common validation path |
4945 | * involves SHUT_WR && listen && SHUT_RD. In case of success, the FD's polling |
4946 | * is disabled. It normally returns non-zero, unless an error is reported. |
4947 | + * It will need to operate under the proxy's lock. The caller is |
4948 | + * responsible for indicating in lpx whether the proxy locks is |
4949 | + * already held (non-zero) or not (zero) so that the function picks it. |
4950 | */ |
4951 | -int pause_listener(struct listener *l) |
4952 | +int pause_listener(struct listener *l, int lpx) |
4953 | { |
4954 | struct proxy *px = l->bind_conf->frontend; |
4955 | int ret = 1; |
4956 | |
4957 | + if (!lpx) |
4958 | + HA_RWLOCK_WRLOCK(PROXY_LOCK, &px->lock); |
4959 | + |
4960 | HA_RWLOCK_WRLOCK(LISTENER_LOCK, &l->lock); |
4961 | |
4962 | if ((global.mode & (MODE_DAEMON | MODE_MWORKER)) && |
4963 | @@ -450,6 +456,10 @@ int pause_listener(struct listener *l) |
4964 | } |
4965 | end: |
4966 | HA_RWLOCK_WRUNLOCK(LISTENER_LOCK, &l->lock); |
4967 | + |
4968 | + if (!lpx) |
4969 | + HA_RWLOCK_WRUNLOCK(PROXY_LOCK, &px->lock); |
4970 | + |
4971 | return ret; |
4972 | } |
4973 | |
4974 | @@ -462,13 +472,19 @@ int pause_listener(struct listener *l) |
4975 | * state, it's totally rebound. This can happen if a pause() has completely |
4976 | * stopped it. If the resume fails, 0 is returned and an error might be |
4977 | * displayed. |
4978 | + * It will need to operate under the proxy's lock. The caller is |
4979 | + * responsible for indicating in lpx whether the proxy locks is |
4980 | + * already held (non-zero) or not (zero) so that the function picks it. |
4981 | */ |
4982 | -int resume_listener(struct listener *l) |
4983 | +int resume_listener(struct listener *l, int lpx) |
4984 | { |
4985 | struct proxy *px = l->bind_conf->frontend; |
4986 | int was_paused = px && px->li_paused; |
4987 | int ret = 1; |
4988 | |
4989 | + if (!lpx) |
4990 | + HA_RWLOCK_WRLOCK(PROXY_LOCK, &px->lock); |
4991 | + |
4992 | HA_RWLOCK_WRLOCK(LISTENER_LOCK, &l->lock); |
4993 | |
4994 | /* check that another thread didn't to the job in parallel (e.g. at the |
4995 | @@ -484,6 +500,10 @@ int resume_listener(struct listener *l) |
4996 | if (l->state == LI_READY) |
4997 | goto end; |
4998 | |
4999 | + /* the listener might have been stopped in parallel */ |
5000 | + if (l->state < LI_PAUSED) |
This needs rebasing, security released 2.4.18-0ubuntu1.3