Merge ~ahasenack/ubuntu/+source/haproxy:disco-haproxy-1.8.19 into ubuntu/+source/haproxy:ubuntu/devel
- Git
- lp:~ahasenack/ubuntu/+source/haproxy
- disco-haproxy-1.8.19
- Merge into ubuntu/devel
Status: | Superseded |
---|---|
Proposed branch: | ~ahasenack/ubuntu/+source/haproxy:disco-haproxy-1.8.19 |
Merge into: | ubuntu/+source/haproxy:ubuntu/devel |
Diff against target: |
1551 lines (+501/-163) (has conflicts) 35 files modified
CHANGELOG (+52/-0) README (+1/-1) VERDATE (+1/-1) VERSION (+1/-1) debian/changelog (+36/-0) debian/control (+2/-1) debian/tests/proxy-localhost (+4/-0) doc/configuration.txt (+57/-43) examples/haproxy.spec (+7/-1) include/common/h2.h (+33/-0) include/common/hpack-tbl.h (+1/-0) include/common/xref.h (+5/-0) include/proto/session.h (+2/-1) include/proto/stream.h (+4/-2) include/proto/stream_interface.h (+6/-0) include/types/connection.h (+1/-0) include/types/stream_interface.h (+19/-17) scripts/announce-release (+2/-0) src/action.c (+5/-0) src/backend.c (+10/-8) src/cache.c (+6/-2) src/cfgparse.c (+52/-8) src/checks.c (+4/-3) src/flt_spoe.c (+42/-25) src/haproxy.c (+1/-0) src/hlua.c (+3/-3) src/hpack-dec.c (+6/-0) src/mux_h2.c (+48/-18) src/proto_http.c (+4/-1) src/sample.c (+7/-0) src/server.c (+22/-26) src/ssl_sock.c (+41/-0) src/stream.c (+5/-1) src/stream_interface.c (+8/-0) src/tcp_rules.c (+3/-0) Conflict in debian/changelog Conflict in debian/tests/proxy-localhost |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Canonical Server | Pending | ||
Review via email: mp+363424@code.launchpad.net |
Commit message
Description of the change
Merge from debian. Our single delta still applies, but it was already accepted by debian and should be in an upcoming release (https:/
I updated the test to use "service" instead of "systemctl" to match what was accepted by debian after my submission.
Unmerged commits
- 9132c04... by Andreas Hasenack
-
update-maintainer
- 1044ad9... by Andreas Hasenack
-
reconstruct-
changelog - ebda99b... by Andreas Hasenack
-
merge-changelogs
- e44336d... by Andreas Hasenack
-
- d/t/control, d/t/proxy-
localhost: simple DEP8 test to actually
generate traffic through haproxy.
[Updated to use "service" instead of "systemctl" to match what was
submitted to Debian.] - bd3810b... by Apollon Oikonomopoulos <email address hidden>
-
Import patches-unapplied version 1.8.19-1 to debian/sid
Imported using git-ubuntu import.
Changelog parent: 3b885bfb277d048
31405e979d38eac 423793855c New changelog entries:
* New upstream version 1.8.19
- BUG/MEDIUM: spoe: initialization depending on nbthread must be done last
- BUG/MEDIUM: server: initialize the idle conns list after parsing the
config
- BUG/MAJOR: spoe: Don't try to get agent config during SPOP healthcheck
- BUG/MAJOR: stream: avoid double free on unique_id (Closes: #921981) - 3b885bf... by Vincent Bernat
-
Import patches-unapplied version 1.8.18-1 to debian/sid
Imported using git-ubuntu import.
Changelog parent: a1a84313d545709
21ed9a0ecd52c2b 23ec5e991e New changelog entries:
* New upstream version 1.8.18
- BUG/MAJOR: cache: fix confusion between zero and uninitialized cache
key
- BUG/MAJOR: config: verify that targets of track-sc and stick rules
are present
- BUG/MAJOR: spoe: verify that backends used by SPOE cover all their
callers' processes
Preview Diff
1 | diff --git a/CHANGELOG b/CHANGELOG |
2 | index 6a8554b..d489531 100644 |
3 | --- a/CHANGELOG |
4 | +++ b/CHANGELOG |
5 | @@ -1,6 +1,58 @@ |
6 | ChangeLog : |
7 | =========== |
8 | |
9 | +2019/02/11 : 1.8.19 |
10 | + - DOC: ssl: Clarify when pre TLSv1.3 cipher can be used |
11 | + - DOC: ssl: Stop documenting ciphers example to use |
12 | + - BUG/MINOR: spoe: do not assume agent->rt is valid on exit |
13 | + - BUG/MINOR: lua: initialize the correct idle conn lists for the SSL sockets |
14 | + - BUG/MEDIUM: spoe: initialization depending on nbthread must be done last |
15 | + - BUG/MEDIUM: server: initialize the idle conns list after parsing the config |
16 | + - BUG/MAJOR: spoe: Don't try to get agent config during SPOP healthcheck |
17 | + - BUG/MAJOR: stream: avoid double free on unique_id |
18 | + - BUG/MINOR: config: Reinforce validity check when a process number is parsed |
19 | + |
20 | +2019/02/06 : 1.8.18 |
21 | + - DOC: http-request cache-use / http-response cache-store expects cache name |
22 | + - BUG/MAJOR: cache: fix confusion between zero and uninitialized cache key |
23 | + - BUG/MEDIUM: ssl: Disable anti-replay protection and set max data with 0RTT. |
24 | + - DOC: Be a bit more explicit about allow-0rtt security implications. |
25 | + - BUG/MEDIUM: ssl: missing allocation failure checks loading tls key file |
26 | + - BUG/MINOR: backend: don't use url_param_name as a hint for BE_LB_ALGO_PH |
27 | + - BUG/MINOR: backend: balance uri specific options were lost across defaults |
28 | + - BUG/MINOR: backend: BE_LB_LKUP_CHTREE is a value, not a bit |
29 | + - BUG/MINOR: stick_table: Prevent conn_cur from underflowing |
30 | + - BUG/MINOR: server: don't always trust srv_check_health when loading a server state |
31 | + - BUG/MINOR: check: Wake the check task if the check is finished in wake_srv_chk() |
32 | + - BUG/MEDIUM: ssl: Fix handling of TLS 1.3 KeyUpdate messages |
33 | + - DOC: mention the effect of nf_conntrack_tcp_loose on src/dst |
34 | + - MINOR: h2: add a bit-based frame type representation |
35 | + - MINOR: h2: declare new sets of frame types |
36 | + - BUG/MINOR: mux-h2: CONTINUATION in closed state must always return GOAWAY |
37 | + - BUG/MINOR: mux-h2: headers-type frames in HREM are always a connection error |
38 | + - BUG/MINOR: mux-h2: make it possible to set the error code on an already closed stream |
39 | + - BUG/MINOR: hpack: return a compression error on invalid table size updates |
40 | + - DOC: nbthread is no longer experimental. |
41 | + - BUG/MINOR: spoe: corrected fragmentation string size |
42 | + - BUG/MINOR: deinit: tcp_rep.inspect_rules not deinit, add to deinit |
43 | + - SCRIPTS: add the slack channel URL to the announce script |
44 | + - SCRIPTS: add the issue tracker URL to the announce script |
45 | + - BUG/MINOR: stream: don't close the front connection when facing a backend error |
46 | + - MINOR: xref: Add missing barriers. |
47 | + - BUG/MEDIUM: mux-h2: wake up flow-controlled streams on initial window update |
48 | + - BUG/MEDIUM: mux-h2: fix two half-closed to closed transitions |
49 | + - BUG/MEDIUM: mux-h2: make sure never to send GOAWAY on too old streams |
50 | + - BUG/MEDIUM: mux-h2: wait for the mux buffer to be empty before closing the connection |
51 | + - MINOR: stream-int: expand the flags to 32-bit |
52 | + - MINOR: stream-int: add a new flag to mention that we want the connection to be killed |
53 | + - MINOR: connstream: have a new flag CS_FL_KILL_CONN to kill a connection |
54 | + - BUG/MEDIUM: mux-h2: do not close the connection on aborted streams |
55 | + - BUG/MEDIUM: stream: Don't forget to free s->unique_id in stream_free(). |
56 | + - BUG/MINOR: config: fix bind line thread mask validation |
57 | + - BUG/MAJOR: config: verify that targets of track-sc and stick rules are present |
58 | + - BUG/MAJOR: spoe: verify that backends used by SPOE cover all their callers' processes |
59 | + - BUG/MINOR: config: make sure to count the error on incorrect track-sc/stick rules |
60 | + |
61 | 2019/01/08 : 1.8.17 |
62 | - BUG/MAJOR: stream-int: Update the stream expiration date in stream_int_notify() |
63 | - MINOR: mux-h2: only increase the connection window with the first update |
64 | diff --git a/README b/README |
65 | index 07e095a..e66b5fd 100644 |
66 | --- a/README |
67 | +++ b/README |
68 | @@ -3,7 +3,7 @@ |
69 | ---------------------- |
70 | version 1.8 |
71 | willy tarreau |
72 | - 2019/01/08 |
73 | + 2019/02/11 |
74 | |
75 | |
76 | 1) How to build it |
77 | diff --git a/VERDATE b/VERDATE |
78 | index 944f490..ddc7727 100644 |
79 | --- a/VERDATE |
80 | +++ b/VERDATE |
81 | @@ -1,2 +1,2 @@ |
82 | $Format:%ci$ |
83 | -2019/01/08 |
84 | +2019/02/11 |
85 | diff --git a/VERSION b/VERSION |
86 | index f49e8ed..c8f955a 100644 |
87 | --- a/VERSION |
88 | +++ b/VERSION |
89 | @@ -1 +1 @@ |
90 | -1.8.17 |
91 | +1.8.19 |
92 | diff --git a/debian/changelog b/debian/changelog |
93 | index 3f24b6e..f461719 100644 |
94 | --- a/debian/changelog |
95 | +++ b/debian/changelog |
96 | @@ -1,3 +1,39 @@ |
97 | +<<<<<<< debian/changelog |
98 | +======= |
99 | +haproxy (1.8.19-1ubuntu1) disco; urgency=medium |
100 | + |
101 | + * Merge with Debian unstable. Remaining changes: |
102 | + - d/t/control, d/t/proxy-localhost: simple DEP8 test to actually |
103 | + generate traffic through haproxy. |
104 | + [Updated to use "service" instead of "systemctl" to match what was |
105 | + submitted to Debian.] |
106 | + |
107 | + -- Andreas Hasenack <andreas@canonical.com> Wed, 20 Feb 2019 14:18:15 +0100 |
108 | + |
109 | +haproxy (1.8.19-1) unstable; urgency=medium |
110 | + |
111 | + * New upstream version 1.8.19 |
112 | + - BUG/MEDIUM: spoe: initialization depending on nbthread must be done last |
113 | + - BUG/MEDIUM: server: initialize the idle conns list after parsing the |
114 | + config |
115 | + - BUG/MAJOR: spoe: Don't try to get agent config during SPOP healthcheck |
116 | + - BUG/MAJOR: stream: avoid double free on unique_id (Closes: #921981) |
117 | + |
118 | + -- Apollon Oikonomopoulos <apoikos@debian.org> Tue, 12 Feb 2019 10:30:54 +0200 |
119 | + |
120 | +haproxy (1.8.18-1) unstable; urgency=medium |
121 | + |
122 | + * New upstream version 1.8.18 |
123 | + - BUG/MAJOR: cache: fix confusion between zero and uninitialized cache |
124 | + key |
125 | + - BUG/MAJOR: config: verify that targets of track-sc and stick rules |
126 | + are present |
127 | + - BUG/MAJOR: spoe: verify that backends used by SPOE cover all their |
128 | + callers' processes |
129 | + |
130 | + -- Vincent Bernat <bernat@debian.org> Wed, 06 Feb 2019 18:44:54 +0100 |
131 | + |
132 | +>>>>>>> debian/changelog |
133 | haproxy (1.8.17-1ubuntu1) disco; urgency=medium |
134 | |
135 | * d/t/control, d/t/proxy-localhost: simple DEP8 test to actually |
136 | diff --git a/debian/control b/debian/control |
137 | index 941d92f..a85b34f 100644 |
138 | --- a/debian/control |
139 | +++ b/debian/control |
140 | @@ -1,7 +1,8 @@ |
141 | Source: haproxy |
142 | Section: net |
143 | Priority: optional |
144 | -Maintainer: Debian HAProxy Maintainers <haproxy@tracker.debian.org> |
145 | +Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com> |
146 | +XSBC-Original-Maintainer: Debian HAProxy Maintainers <haproxy@tracker.debian.org> |
147 | Uploaders: Apollon Oikonomopoulos <apoikos@debian.org>, |
148 | Prach Pongpanich <prach@debian.org>, |
149 | Vincent Bernat <bernat@debian.org> |
150 | diff --git a/debian/tests/proxy-localhost b/debian/tests/proxy-localhost |
151 | index 2824287..b7762d5 100644 |
152 | --- a/debian/tests/proxy-localhost |
153 | +++ b/debian/tests/proxy-localhost |
154 | @@ -33,7 +33,11 @@ backend test-back |
155 | server test-1 localhost:80 |
156 | EOF |
157 | |
158 | +<<<<<<< debian/tests/proxy-localhost |
159 | systemctl restart haproxy |
160 | +======= |
161 | +service haproxy restart |
162 | +>>>>>>> debian/tests/proxy-localhost |
163 | |
164 | # index.html is shipped with apache2 |
165 | # Download it via haproxy and compare |
166 | diff --git a/doc/configuration.txt b/doc/configuration.txt |
167 | index 4f999e2..8d75d56 100644 |
168 | --- a/doc/configuration.txt |
169 | +++ b/doc/configuration.txt |
170 | @@ -4,7 +4,7 @@ |
171 | ---------------------- |
172 | version 1.8 |
173 | willy tarreau |
174 | - 2019/01/08 |
175 | + 2019/02/11 |
176 | |
177 | |
178 | This document covers the configuration language as implemented in the version |
179 | @@ -917,14 +917,14 @@ nbproc <number> |
180 | mode. By default, only one process is created, which is the recommended mode |
181 | of operation. For systems limited to small sets of file descriptors per |
182 | process, it may be needed to fork multiple daemons. USING MULTIPLE PROCESSES |
183 | - IS HARDER TO DEBUG AND IS REALLY DISCOURAGED. See also "daemon". |
184 | + IS HARDER TO DEBUG AND IS REALLY DISCOURAGED. See also "daemon" and |
185 | + "nbthread". |
186 | |
187 | nbthread <number> |
188 | This setting is only available when support for threads was built in. It |
189 | creates <number> threads for each created processes. It means if HAProxy is |
190 | started in foreground, it only creates <number> threads for the first |
191 | - process. FOR NOW, THREADS SUPPORT IN HAPROXY IS HIGHLY EXPERIMENTAL AND IT |
192 | - MUST BE ENABLED WITH CAUTION AND AT YOUR OWN RISK. See also "nbproc". |
193 | + process. See also "nbproc". |
194 | |
195 | pidfile <pidfile> |
196 | Writes PIDs of all daemons into file <pidfile>. This option is equivalent to |
197 | @@ -986,12 +986,14 @@ setenv <name> <value> |
198 | ssl-default-bind-ciphers <ciphers> |
199 | This setting is only available when support for OpenSSL was built in. It sets |
200 | the default string describing the list of cipher algorithms ("cipher suite") |
201 | - that are negotiated during the SSL/TLS handshake except for TLSv1.3 for all |
202 | + that are negotiated during the SSL/TLS handshake up to TLSv1.2 for all |
203 | "bind" lines which do not explicitly define theirs. The format of the string |
204 | - is defined in "man 1 ciphers" from OpenSSL man pages, and can be for instance |
205 | - a string such as "AES:ALL:!aNULL:!eNULL:+RC4:@STRENGTH" (without quotes). For |
206 | - TLSv1.3 cipher configuration, please check the "ssl-default-bind-ciphersuites" |
207 | - keyword. Please check the "bind" keyword for more information. |
208 | + is defined in "man 1 ciphers" from OpenSSL man pages. For background |
209 | + information and recommendations see e.g. |
210 | + (https://wiki.mozilla.org/Security/Server_Side_TLS) and |
211 | + (https://mozilla.github.io/server-side-tls/ssl-config-generator/). For TLSv1.3 |
212 | + cipher configuration, please check the "ssl-default-bind-ciphersuites" keyword. |
213 | + Please check the "bind" keyword for more information. |
214 | |
215 | ssl-default-bind-ciphersuites <ciphersuites> |
216 | This setting is only available when support for OpenSSL was built in and |
217 | @@ -999,11 +1001,9 @@ ssl-default-bind-ciphersuites <ciphersuites> |
218 | describing the list of cipher algorithms ("cipher suite") that are negotiated |
219 | during the TLSv1.3 handshake for all "bind" lines which do not explicitly define |
220 | theirs. The format of the string is defined in |
221 | - "man 1 ciphers" from OpenSSL man pages under the section "ciphersuites", and can |
222 | - be for instance a string such as |
223 | - "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256" |
224 | - (without quotes). For cipher configuration for TLSv1.2 and earlier, please check |
225 | - the "ssl-default-bind-ciphers" keyword. Please check the "bind" keyword for more |
226 | + "man 1 ciphers" from OpenSSL man pages under the section "ciphersuites". For |
227 | + cipher configuration for TLSv1.2 and earlier, please check the |
228 | + "ssl-default-bind-ciphers" keyword. Please check the "bind" keyword for more |
229 | information. |
230 | |
231 | ssl-default-bind-options [<option>]... |
232 | @@ -1018,11 +1018,15 @@ ssl-default-bind-options [<option>]... |
233 | ssl-default-server-ciphers <ciphers> |
234 | This setting is only available when support for OpenSSL was built in. It |
235 | sets the default string describing the list of cipher algorithms that are |
236 | - negotiated during the SSL/TLS handshake except for TLSv1.3 with the server, |
237 | + negotiated during the SSL/TLS handshake up to TLSv1.2 with the server, |
238 | for all "server" lines which do not explicitly define theirs. The format of |
239 | - the string is defined in "man 1 ciphers". For TLSv1.3 cipher configuration, |
240 | - please check the "ssl-default-server-ciphersuites" keyword. Please check the |
241 | - "server" keyword for more information. |
242 | + the string is defined in "man 1 ciphers" from OpenSSL man pages. For background |
243 | + information and recommendations see e.g. |
244 | + (https://wiki.mozilla.org/Security/Server_Side_TLS) and |
245 | + (https://mozilla.github.io/server-side-tls/ssl-config-generator/). |
246 | + For TLSv1.3 cipher configuration, please check the |
247 | + "ssl-default-server-ciphersuites" keyword. Please check the "server" keyword |
248 | + for more information. |
249 | |
250 | ssl-default-server-ciphersuites <ciphersuites> |
251 | This setting is only available when support for OpenSSL was built in and |
252 | @@ -1030,9 +1034,10 @@ ssl-default-server-ciphersuites <ciphersuites> |
253 | string describing the list of cipher algorithms that are negotiated during |
254 | the TLSv1.3 handshake with the server, for all "server" lines which do not |
255 | explicitly define theirs. The format of the string is defined in |
256 | - "man 1 ciphers" under the "ciphersuites" section. For cipher configuration for |
257 | - TLSv1.2 and earlier, please check the "ssl-default-server-ciphers" keyword. |
258 | - Please check the "server" keyword for more information. |
259 | + "man 1 ciphers" from OpenSSL man pages under the section "ciphersuites". For |
260 | + cipher configuration for TLSv1.2 and earlier, please check the |
261 | + "ssl-default-server-ciphers" keyword. Please check the "server" keyword for |
262 | + more information. |
263 | |
264 | ssl-default-server-options [<option>]... |
265 | This setting is only available when support for OpenSSL was built in. It sets |
266 | @@ -10483,7 +10488,10 @@ accept-proxy |
267 | |
268 | allow-0rtt |
269 | Allow receiving early data when using TLSv1.3. This is disabled by default, |
270 | - due to security considerations. |
271 | + due to security considerations. Because it is vulnerable to replay attacks, |
272 | + you should only allow if for requests that are safe to replay, ie requests |
273 | + that are idempotent. You can use the "wait-for-handshake" action for any |
274 | + request that wouldn't be safe with early data. |
275 | |
276 | alpn <protocols> |
277 | This enables the TLS ALPN extension and advertises the specified protocol |
278 | @@ -10545,11 +10553,8 @@ ca-sign-pass <passphrase> |
279 | ciphers <ciphers> |
280 | This setting is only available when support for OpenSSL was built in. It sets |
281 | the string describing the list of cipher algorithms ("cipher suite") that are |
282 | - negotiated during the SSL/TLS handshake except for TLSv1.3. The format of the |
283 | - string is defined in "man 1 ciphers" from OpenSSL man pages, and can be for |
284 | - instance a string such as "AES:ALL:!aNULL:!eNULL:+RC4:@STRENGTH" (without |
285 | - quotes). Depending on the compatibility and security requirements, the list |
286 | - of suitable ciphers depends on a variety of variables. For background |
287 | + negotiated during the SSL/TLS handshake up to TLSv1.2. The format of the |
288 | + string is defined in "man 1 ciphers" from OpenSSL man pages. For background |
289 | information and recommendations see e.g. |
290 | (https://wiki.mozilla.org/Security/Server_Side_TLS) and |
291 | (https://mozilla.github.io/server-side-tls/ssl-config-generator/). For TLSv1.3 |
292 | @@ -10560,11 +10565,8 @@ ciphersuites <ciphersuites> |
293 | OpenSSL 1.1.1 or later was used to build HAProxy. It sets the string describing |
294 | the list of cipher algorithms ("cipher suite") that are negotiated during the |
295 | TLSv1.3 handshake. The format of the string is defined in "man 1 ciphers" from |
296 | - OpenSSL man pages under the "ciphersuites" section, and can be for instance a |
297 | - string such as |
298 | - "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256" |
299 | - (without quotes). For cipher configuration for TLSv1.2 and earlier, please check |
300 | - the "ciphers" keyword. |
301 | + OpenSSL man pages under the "ciphersuites" section. For cipher configuration |
302 | + for TLSv1.2 and earlier, please check the "ciphers" keyword. |
303 | |
304 | crl-file <crlfile> |
305 | This setting is only available when support for OpenSSL was built in. It |
306 | @@ -11278,19 +11280,20 @@ ciphers <ciphers> |
307 | This setting is only available when support for OpenSSL was built in. This |
308 | option sets the string describing the list of cipher algorithms that is |
309 | negotiated during the SSL/TLS handshake with the server. The format of the |
310 | - string is defined in "man 1 ciphers". When SSL is used to communicate with |
311 | - servers on the local network, it is common to see a weaker set of algorithms |
312 | - than what is used over the internet. Doing so reduces CPU usage on both the |
313 | - server and haproxy while still keeping it compatible with deployed software. |
314 | - Some algorithms such as RC4-SHA1 are reasonably cheap. If no security at all |
315 | - is needed and just connectivity, using DES can be appropriate. |
316 | + string is defined in "man 1 ciphers" from OpenSSL man pages. For background |
317 | + information and recommendations see e.g. |
318 | + (https://wiki.mozilla.org/Security/Server_Side_TLS) and |
319 | + (https://mozilla.github.io/server-side-tls/ssl-config-generator/). For TLSv1.3 |
320 | + cipher configuration, please check the "ciphersuites" keyword. |
321 | |
322 | ciphersuites <ciphersuites> |
323 | This setting is only available when support for OpenSSL was built in and |
324 | OpenSSL 1.1.1 or later was used to build HAProxy. This option sets the string |
325 | describing the list of cipher algorithms that is negotiated during the TLS |
326 | 1.3 handshake with the server. The format of the string is defined in |
327 | - "man 1 ciphers" under the "ciphersuites" section. |
328 | + "man 1 ciphers" from OpenSSL man pages under the "ciphersuites" section. |
329 | + For cipher configuration for TLSv1.2 and earlier, please check the "ciphers" |
330 | + keyword. |
331 | |
332 | cookie <value> |
333 | The "cookie" parameter sets the cookie value assigned to the server to |
334 | @@ -13819,7 +13822,12 @@ dst : ip |
335 | which is the address the client connected to. It can be useful when running |
336 | in transparent mode. It is of type IP and works on both IPv4 and IPv6 tables. |
337 | On IPv6 tables, IPv4 address is mapped to its IPv6 equivalent, according to |
338 | - RFC 4291. |
339 | + RFC 4291. When the incoming connection passed through address translation or |
340 | + redirection involving connection tracking, the original destination address |
341 | + before the redirection will be reported. On Linux systems, the source and |
342 | + destination may seldom appear reversed if the nf_conntrack_tcp_loose sysctl |
343 | + is set, because a late response may reopen a timed out connection and switch |
344 | + what is believed to be the source and the destination. |
345 | |
346 | dst_conn : integer |
347 | Returns an integer value corresponding to the number of currently established |
348 | @@ -14124,7 +14132,13 @@ src : ip |
349 | behind a proxy. However if the "accept-proxy" or "accept-netscaler-cip" bind |
350 | directive is used, it can be the address of a client behind another |
351 | PROXY-protocol compatible component for all rule sets except |
352 | - "tcp-request connection" which sees the real address. |
353 | + "tcp-request connection" which sees the real address. When the incoming |
354 | + connection passed through address translation or redirection involving |
355 | + connection tracking, the original destination address before the redirection |
356 | + will be reported. On Linux systems, the source and destination may seldom |
357 | + appear reversed if the nf_conntrack_tcp_loose sysctl is set, because a late |
358 | + response may reopen a timed out connection and switch what is believed to be |
359 | + the source and the destination. |
360 | |
361 | Example: |
362 | # add an HTTP header in requests with the originating address' country |
363 | @@ -17157,13 +17171,13 @@ max-age <seconds> |
364 | 10.2.2. Proxy section |
365 | --------------------- |
366 | |
367 | -http-request cache-use <name> |
368 | +http-request cache-use <name> [ { if | unless } <condition> ] |
369 | Try to deliver a cached object from the cache <name>. This directive is also |
370 | mandatory to store the cache as it calculates the cache hash. If you want to |
371 | use a condition for both storage and delivering that's a good idea to put it |
372 | after this one. |
373 | |
374 | -http-response cache-store <name> |
375 | +http-response cache-store <name> [ { if | unless } <condition> ] |
376 | Store an http-response within the cache. The storage of the response headers |
377 | is done at this step, which means you can use others http-response actions |
378 | to modify headers before or after the storage of the response. This action |
379 | diff --git a/examples/haproxy.spec b/examples/haproxy.spec |
380 | index 15f0850..aaa83c8 100644 |
381 | --- a/examples/haproxy.spec |
382 | +++ b/examples/haproxy.spec |
383 | @@ -1,6 +1,6 @@ |
384 | Summary: HA-Proxy is a TCP/HTTP reverse proxy for high availability environments |
385 | Name: haproxy |
386 | -Version: 1.8.17 |
387 | +Version: 1.8.19 |
388 | Release: 1 |
389 | License: GPL |
390 | Group: System Environment/Daemons |
391 | @@ -74,6 +74,12 @@ fi |
392 | %attr(0755,root,root) %config %{_sysconfdir}/rc.d/init.d/%{name} |
393 | |
394 | %changelog |
395 | +* Mon Feb 11 2019 Willy Tarreau <w@1wt.eu> |
396 | +- updated to 1.8.19 |
397 | + |
398 | +* Wed Feb 6 2019 Willy Tarreau <w@1wt.eu> |
399 | +- updated to 1.8.18 |
400 | + |
401 | * Tue Jan 8 2019 Willy Tarreau <w@1wt.eu> |
402 | - updated to 1.8.17 |
403 | |
404 | diff --git a/include/common/h2.h b/include/common/h2.h |
405 | index 576ed10..dec1763 100644 |
406 | --- a/include/common/h2.h |
407 | +++ b/include/common/h2.h |
408 | @@ -81,6 +81,30 @@ enum h2_ft { |
409 | H2_FT_ENTRIES /* must be last */ |
410 | } __attribute__((packed)); |
411 | |
412 | +/* frame types, turned to bits or bit fields */ |
413 | +enum { |
414 | + /* one bit per frame type */ |
415 | + H2_FT_DATA_BIT = 1U << H2_FT_DATA, |
416 | + H2_FT_HEADERS_BIT = 1U << H2_FT_HEADERS, |
417 | + H2_FT_PRIORITY_BIT = 1U << H2_FT_PRIORITY, |
418 | + H2_FT_RST_STREAM_BIT = 1U << H2_FT_RST_STREAM, |
419 | + H2_FT_SETTINGS_BIT = 1U << H2_FT_SETTINGS, |
420 | + H2_FT_PUSH_PROMISE_BIT = 1U << H2_FT_PUSH_PROMISE, |
421 | + H2_FT_PING_BIT = 1U << H2_FT_PING, |
422 | + H2_FT_GOAWAY_BIT = 1U << H2_FT_GOAWAY, |
423 | + H2_FT_WINDOW_UPDATE_BIT = 1U << H2_FT_WINDOW_UPDATE, |
424 | + H2_FT_CONTINUATION_BIT = 1U << H2_FT_CONTINUATION, |
425 | + /* padded frames */ |
426 | + H2_FT_PADDED_MASK = H2_FT_DATA_BIT | H2_FT_HEADERS_BIT | H2_FT_PUSH_PROMISE_BIT, |
427 | + /* flow controlled frames */ |
428 | + H2_FT_FC_MASK = H2_FT_DATA_BIT, |
429 | + /* header frames */ |
430 | + H2_FT_HDR_MASK = H2_FT_HEADERS_BIT | H2_FT_PUSH_PROMISE_BIT | H2_FT_CONTINUATION_BIT, |
431 | + /* frames allowed to arrive late on a stream */ |
432 | + H2_FT_LATE_MASK = H2_FT_WINDOW_UPDATE_BIT | H2_FT_RST_STREAM_BIT | H2_FT_PRIORITY_BIT, |
433 | +}; |
434 | + |
435 | + |
436 | /* flags defined for each frame type */ |
437 | |
438 | // RFC7540 #6.1 |
439 | @@ -109,6 +133,9 @@ enum h2_ft { |
440 | // RFC7540 #6.8 : GOAWAY defines no flags |
441 | // RFC7540 #6.9 : WINDOW_UPDATE defines no flags |
442 | |
443 | +// PADDED is the exact same among DATA, HEADERS and PUSH_PROMISE (8) |
444 | +#define H2_F_PADDED 0x08 |
445 | + |
446 | /* HTTP/2 error codes - RFC7540 #7 */ |
447 | enum h2_err { |
448 | H2_ERR_NO_ERROR = 0x0, |
449 | @@ -159,6 +186,12 @@ int h2_make_h1_request(struct http_hdr *list, char *out, int osize, unsigned int |
450 | * Some helpful debugging functions. |
451 | */ |
452 | |
453 | +/* returns a bit corresponding to the frame type */ |
454 | +static inline unsigned int h2_ft_bit(enum h2_ft ft) |
455 | +{ |
456 | + return 1U << ft; |
457 | +} |
458 | + |
459 | /* returns the frame type as a string */ |
460 | static inline const char *h2_ft_str(int type) |
461 | { |
462 | diff --git a/include/common/hpack-tbl.h b/include/common/hpack-tbl.h |
463 | index 385f386..2cbc2bf 100644 |
464 | --- a/include/common/hpack-tbl.h |
465 | +++ b/include/common/hpack-tbl.h |
466 | @@ -127,6 +127,7 @@ enum { |
467 | HPACK_ERR_MISSING_AUTHORITY, /* :authority is missing with CONNECT */ |
468 | HPACK_ERR_SCHEME_NOT_ALLOWED, /* :scheme not allowed with CONNECT */ |
469 | HPACK_ERR_PATH_NOT_ALLOWED, /* :path not allowed with CONNECT */ |
470 | + HPACK_ERR_INVALID_ARGUMENT, /* an invalid argument was passed */ |
471 | }; |
472 | |
473 | /* static header table as in RFC7541 Appendix A. [0] unused. */ |
474 | diff --git a/include/common/xref.h b/include/common/xref.h |
475 | index 6dfa7b6..a6291f5 100644 |
476 | --- a/include/common/xref.h |
477 | +++ b/include/common/xref.h |
478 | @@ -32,6 +32,7 @@ static inline struct xref *xref_get_peer_and_lock(struct xref *xref) |
479 | |
480 | /* Get the local pointer to the peer. */ |
481 | local = HA_ATOMIC_XCHG(&xref->peer, XREF_BUSY); |
482 | + __ha_barrier_store(); |
483 | |
484 | /* If the local pointer is NULL, the peer no longer exists. */ |
485 | if (local == NULL) { |
486 | @@ -53,6 +54,7 @@ static inline struct xref *xref_get_peer_and_lock(struct xref *xref) |
487 | /* The remote lock is BUSY, We retry the process. */ |
488 | if (remote == XREF_BUSY) { |
489 | xref->peer = local; |
490 | + __ha_barrier_store(); |
491 | continue; |
492 | } |
493 | |
494 | @@ -66,6 +68,8 @@ static inline void xref_unlock(struct xref *xref, struct xref *peer) |
495 | /* Release the peer. */ |
496 | peer->peer = xref; |
497 | |
498 | + __ha_barrier_store(); |
499 | + |
500 | /* Release myself. */ |
501 | xref->peer = peer; |
502 | } |
503 | @@ -73,6 +77,7 @@ static inline void xref_unlock(struct xref *xref, struct xref *peer) |
504 | static inline void xref_disconnect(struct xref *xref, struct xref *peer) |
505 | { |
506 | peer->peer = NULL; |
507 | + __ha_barrier_store(); |
508 | xref->peer = NULL; |
509 | } |
510 | |
511 | diff --git a/include/proto/session.h b/include/proto/session.h |
512 | index f48c0d4..7265f5a 100644 |
513 | --- a/include/proto/session.h |
514 | +++ b/include/proto/session.h |
515 | @@ -59,7 +59,8 @@ static inline void session_store_counters(struct session *sess) |
516 | if (ptr) { |
517 | HA_RWLOCK_WRLOCK(STK_SESS_LOCK, &ts->lock); |
518 | |
519 | - stktable_data_cast(ptr, conn_cur)--; |
520 | + if (stktable_data_cast(ptr, conn_cur) > 0) |
521 | + stktable_data_cast(ptr, conn_cur)--; |
522 | |
523 | HA_RWLOCK_WRUNLOCK(STK_SESS_LOCK, &ts->lock); |
524 | |
525 | diff --git a/include/proto/stream.h b/include/proto/stream.h |
526 | index 8521957..c9bcac3 100644 |
527 | --- a/include/proto/stream.h |
528 | +++ b/include/proto/stream.h |
529 | @@ -104,7 +104,8 @@ static inline void stream_store_counters(struct stream *s) |
530 | if (ptr) { |
531 | HA_RWLOCK_WRLOCK(STK_SESS_LOCK, &ts->lock); |
532 | |
533 | - stktable_data_cast(ptr, conn_cur)--; |
534 | + if (stktable_data_cast(ptr, conn_cur) > 0) |
535 | + stktable_data_cast(ptr, conn_cur)--; |
536 | |
537 | HA_RWLOCK_WRUNLOCK(STK_SESS_LOCK, &ts->lock); |
538 | |
539 | @@ -142,7 +143,8 @@ static inline void stream_stop_content_counters(struct stream *s) |
540 | if (ptr) { |
541 | HA_RWLOCK_WRLOCK(STK_SESS_LOCK, &ts->lock); |
542 | |
543 | - stktable_data_cast(ptr, conn_cur)--; |
544 | + if (stktable_data_cast(ptr, conn_cur) > 0) |
545 | + stktable_data_cast(ptr, conn_cur)--; |
546 | |
547 | HA_RWLOCK_WRUNLOCK(STK_SESS_LOCK, &ts->lock); |
548 | |
549 | diff --git a/include/proto/stream_interface.h b/include/proto/stream_interface.h |
550 | index ee1fa12..9db7920 100644 |
551 | --- a/include/proto/stream_interface.h |
552 | +++ b/include/proto/stream_interface.h |
553 | @@ -320,6 +320,12 @@ static inline void si_shutw(struct stream_interface *si) |
554 | si->ops->shutw(si); |
555 | } |
556 | |
557 | +/* Marks on the stream-interface that next shutw must kill the whole connection */ |
558 | +static inline void si_must_kill_conn(struct stream_interface *si) |
559 | +{ |
560 | + si->flags |= SI_FL_KILL_CONN; |
561 | +} |
562 | + |
563 | /* Updates the stream interface and timers, then updates the data layer below */ |
564 | static inline void si_update(struct stream_interface *si) |
565 | { |
566 | diff --git a/include/types/connection.h b/include/types/connection.h |
567 | index b9e4604..c1d1b35 100644 |
568 | --- a/include/types/connection.h |
569 | +++ b/include/types/connection.h |
570 | @@ -70,6 +70,7 @@ enum { |
571 | CS_FL_ERROR = 0x00000100, /* a fatal error was reported */ |
572 | CS_FL_RCV_MORE = 0x00000200, /* more bytes to receive but not enough room */ |
573 | CS_FL_EOS = 0x00001000, /* End of stream */ |
574 | + CS_FL_KILL_CONN = 0x00002000, /* must kill the connection when the CS closes */ |
575 | }; |
576 | |
577 | /* cs_shutr() modes */ |
578 | diff --git a/include/types/stream_interface.h b/include/types/stream_interface.h |
579 | index 0c83759..c805685 100644 |
580 | --- a/include/types/stream_interface.h |
581 | +++ b/include/types/stream_interface.h |
582 | @@ -59,22 +59,23 @@ enum { |
583 | SI_ET_DATA_ABRT = 0x0400, /* data phase aborted by external cause */ |
584 | }; |
585 | |
586 | -/* flags set after I/O (16 bit) */ |
587 | +/* flags set after I/O (32 bit) */ |
588 | enum { |
589 | - SI_FL_NONE = 0x0000, /* nothing */ |
590 | - SI_FL_EXP = 0x0001, /* timeout has expired */ |
591 | - SI_FL_ERR = 0x0002, /* a non-recoverable error has occurred */ |
592 | - SI_FL_WAIT_ROOM = 0x0004, /* waiting for space to store incoming data */ |
593 | - SI_FL_WAIT_DATA = 0x0008, /* waiting for more data to send */ |
594 | - SI_FL_ISBACK = 0x0010, /* 0 for front-side SI, 1 for back-side */ |
595 | - SI_FL_DONT_WAKE = 0x0020, /* resync in progress, don't wake up */ |
596 | - SI_FL_INDEP_STR = 0x0040, /* independent streams = don't update rex on write */ |
597 | - SI_FL_NOLINGER = 0x0080, /* may close without lingering. One-shot. */ |
598 | - SI_FL_NOHALF = 0x0100, /* no half close, close both sides at once */ |
599 | - SI_FL_SRC_ADDR = 0x1000, /* get the source ip/port with getsockname */ |
600 | - SI_FL_WANT_PUT = 0x2000, /* an applet would like to put some data into the buffer */ |
601 | - SI_FL_WANT_GET = 0x4000, /* an applet would like to get some data from the buffer */ |
602 | - SI_FL_CLEAN_ABRT = 0x8000, /* SI_FL_ERR is used to report aborts, and not SHUTR */ |
603 | + SI_FL_NONE = 0x00000000, /* nothing */ |
604 | + SI_FL_EXP = 0x00000001, /* timeout has expired */ |
605 | + SI_FL_ERR = 0x00000002, /* a non-recoverable error has occurred */ |
606 | + SI_FL_WAIT_ROOM = 0x00000004, /* waiting for space to store incoming data */ |
607 | + SI_FL_WAIT_DATA = 0x00000008, /* waiting for more data to send */ |
608 | + SI_FL_ISBACK = 0x00000010, /* 0 for front-side SI, 1 for back-side */ |
609 | + SI_FL_DONT_WAKE = 0x00000020, /* resync in progress, don't wake up */ |
610 | + SI_FL_INDEP_STR = 0x00000040, /* independent streams = don't update rex on write */ |
611 | + SI_FL_NOLINGER = 0x00000080, /* may close without lingering. One-shot. */ |
612 | + SI_FL_NOHALF = 0x00000100, /* no half close, close both sides at once */ |
613 | + SI_FL_SRC_ADDR = 0x00001000, /* get the source ip/port with getsockname */ |
614 | + SI_FL_WANT_PUT = 0x00002000, /* an applet would like to put some data into the buffer */ |
615 | + SI_FL_WANT_GET = 0x00004000, /* an applet would like to get some data from the buffer */ |
616 | + SI_FL_CLEAN_ABRT = 0x00008000, /* SI_FL_ERR is used to report aborts, and not SHUTR */ |
617 | + SI_FL_KILL_CONN = 0x00010000, /* next shutw must kill the whole conn, not just the stream */ |
618 | }; |
619 | |
620 | /* A stream interface has 3 parts : |
621 | @@ -92,10 +93,11 @@ struct stream_interface { |
622 | /* struct members used by the "buffer" side */ |
623 | enum si_state state; /* SI_ST* */ |
624 | enum si_state prev_state;/* SI_ST*, copy of previous state */ |
625 | - unsigned short flags; /* SI_FL_* */ |
626 | - unsigned int exp; /* wake up time for connect, queue, turn-around, ... */ |
627 | + /* 16-bit hole here */ |
628 | + unsigned int flags; /* SI_FL_* */ |
629 | enum obj_type *end; /* points to the end point (connection or appctx) */ |
630 | struct si_ops *ops; /* general operations at the stream interface layer */ |
631 | + unsigned int exp; /* wake up time for connect, queue, turn-around, ... */ |
632 | |
633 | /* struct members below are the "remote" part, as seen from the buffer side */ |
634 | unsigned int err_type; /* first error detected, one of SI_ET_* */ |
635 | diff --git a/scripts/announce-release b/scripts/announce-release |
636 | index c4045ae..972d6ea 100755 |
637 | --- a/scripts/announce-release |
638 | +++ b/scripts/announce-release |
639 | @@ -155,6 +155,8 @@ fi |
640 | (echo "Please find the usual URLs below :" |
641 | echo " Site index : http://www.haproxy.org/" |
642 | echo " Discourse : http://discourse.haproxy.org/" |
643 | + echo " Slack channel : https://slack.haproxy.org/" |
644 | + echo " Issue tracker : https://github.com/haproxy/haproxy/issues" |
645 | echo " Sources : http://www.haproxy.org/download/${BRANCH}/src/" |
646 | echo " Git repository : http://git.haproxy.org/git/${gitdir}/" |
647 | echo " Git Web browsing : http://git.haproxy.org/?p=${gitdir}" |
648 | diff --git a/src/action.c b/src/action.c |
649 | index 54d27a0..7574fba 100644 |
650 | --- a/src/action.c |
651 | +++ b/src/action.c |
652 | @@ -51,6 +51,11 @@ int check_trk_action(struct act_rule *rule, struct proxy *px, char **err) |
653 | trk_idx(rule->action)); |
654 | return 0; |
655 | } |
656 | + else if (px->bind_proc & ~target->bind_proc) { |
657 | + memprintf(err, "stick-table '%s' referenced by 'track-sc%d' rule not present on all processes covered by proxy '%s'", |
658 | + target->id, trk_idx(rule->action), px->id); |
659 | + return 0; |
660 | + } |
661 | else { |
662 | free(rule->arg.trk_ctr.table.n); |
663 | rule->arg.trk_ctr.table.t = &target->table; |
664 | diff --git a/src/backend.c b/src/backend.c |
665 | index 87327f1..0cf14cf 100644 |
666 | --- a/src/backend.c |
667 | +++ b/src/backend.c |
668 | @@ -183,7 +183,7 @@ static struct server *get_server_sh(struct proxy *px, const char *addr, int len, |
669 | if ((px->lbprm.algo & BE_LB_HASH_MOD) == BE_LB_HMOD_AVAL) |
670 | h = full_hash(h); |
671 | hash_done: |
672 | - if (px->lbprm.algo & BE_LB_LKUP_CHTREE) |
673 | + if ((px->lbprm.algo & BE_LB_LKUP) == BE_LB_LKUP_CHTREE) |
674 | return chash_get_server_hash(px, h, avoid); |
675 | else |
676 | return map_get_server_hash(px, h); |
677 | @@ -236,7 +236,7 @@ static struct server *get_server_uh(struct proxy *px, char *uri, int uri_len, co |
678 | if ((px->lbprm.algo & BE_LB_HASH_MOD) == BE_LB_HMOD_AVAL) |
679 | hash = full_hash(hash); |
680 | hash_done: |
681 | - if (px->lbprm.algo & BE_LB_LKUP_CHTREE) |
682 | + if ((px->lbprm.algo & BE_LB_LKUP) == BE_LB_LKUP_CHTREE) |
683 | return chash_get_server_hash(px, hash, avoid); |
684 | else |
685 | return map_get_server_hash(px, hash); |
686 | @@ -293,7 +293,7 @@ static struct server *get_server_ph(struct proxy *px, const char *uri, int uri_l |
687 | if ((px->lbprm.algo & BE_LB_HASH_MOD) == BE_LB_HMOD_AVAL) |
688 | hash = full_hash(hash); |
689 | |
690 | - if (px->lbprm.algo & BE_LB_LKUP_CHTREE) |
691 | + if ((px->lbprm.algo & BE_LB_LKUP) == BE_LB_LKUP_CHTREE) |
692 | return chash_get_server_hash(px, hash, avoid); |
693 | else |
694 | return map_get_server_hash(px, hash); |
695 | @@ -367,7 +367,7 @@ static struct server *get_server_ph_post(struct stream *s, const struct server * |
696 | if ((px->lbprm.algo & BE_LB_HASH_MOD) == BE_LB_HMOD_AVAL) |
697 | hash = full_hash(hash); |
698 | |
699 | - if (px->lbprm.algo & BE_LB_LKUP_CHTREE) |
700 | + if ((px->lbprm.algo & BE_LB_LKUP) == BE_LB_LKUP_CHTREE) |
701 | return chash_get_server_hash(px, hash, avoid); |
702 | else |
703 | return map_get_server_hash(px, hash); |
704 | @@ -463,7 +463,7 @@ static struct server *get_server_hh(struct stream *s, const struct server *avoid |
705 | if ((px->lbprm.algo & BE_LB_HASH_MOD) == BE_LB_HMOD_AVAL) |
706 | hash = full_hash(hash); |
707 | hash_done: |
708 | - if (px->lbprm.algo & BE_LB_LKUP_CHTREE) |
709 | + if ((px->lbprm.algo & BE_LB_LKUP) == BE_LB_LKUP_CHTREE) |
710 | return chash_get_server_hash(px, hash, avoid); |
711 | else |
712 | return map_get_server_hash(px, hash); |
713 | @@ -507,7 +507,7 @@ static struct server *get_server_rch(struct stream *s, const struct server *avoi |
714 | if ((px->lbprm.algo & BE_LB_HASH_MOD) == BE_LB_HMOD_AVAL) |
715 | hash = full_hash(hash); |
716 | hash_done: |
717 | - if (px->lbprm.algo & BE_LB_LKUP_CHTREE) |
718 | + if ((px->lbprm.algo & BE_LB_LKUP) == BE_LB_LKUP_CHTREE) |
719 | return chash_get_server_hash(px, hash, avoid); |
720 | else |
721 | return map_get_server_hash(px, hash); |
722 | @@ -615,7 +615,7 @@ int assign_server(struct stream *s) |
723 | case BE_LB_LKUP_CHTREE: |
724 | case BE_LB_LKUP_MAP: |
725 | if ((s->be->lbprm.algo & BE_LB_KIND) == BE_LB_KIND_RR) { |
726 | - if (s->be->lbprm.algo & BE_LB_LKUP_CHTREE) |
727 | + if ((s->be->lbprm.algo & BE_LB_LKUP) == BE_LB_LKUP_CHTREE) |
728 | srv = chash_get_next_server(s->be, prev_srv); |
729 | else |
730 | srv = map_get_server_rr(s->be, prev_srv); |
731 | @@ -691,7 +691,7 @@ int assign_server(struct stream *s) |
732 | * back to round robin on the map. |
733 | */ |
734 | if (!srv) { |
735 | - if (s->be->lbprm.algo & BE_LB_LKUP_CHTREE) |
736 | + if ((s->be->lbprm.algo & BE_LB_LKUP) == BE_LB_LKUP_CHTREE) |
737 | srv = chash_get_next_server(s->be, prev_srv); |
738 | else |
739 | srv = map_get_server_rr(s->be, prev_srv); |
740 | @@ -1516,6 +1516,8 @@ int backend_parse_balance(const char **args, char **err, struct proxy *curproxy) |
741 | curproxy->lbprm.algo |= BE_LB_ALGO_UH; |
742 | |
743 | curproxy->uri_whole = 0; |
744 | + curproxy->uri_len_limit = 0; |
745 | + curproxy->uri_dirs_depth1 = 0; |
746 | |
747 | while (*args[arg]) { |
748 | if (!strcmp(args[arg], "len")) { |
749 | diff --git a/src/cache.c b/src/cache.c |
750 | index 667cede..3d8ed24 100644 |
751 | --- a/src/cache.c |
752 | +++ b/src/cache.c |
753 | @@ -400,7 +400,7 @@ enum act_return http_action_store_cache(struct act_rule *rule, struct proxy *px, |
754 | struct cache *cache = (struct cache *)rule->arg.act.p[0]; |
755 | struct shared_context *shctx = shctx_ptr(cache); |
756 | struct cache_entry *object; |
757 | - |
758 | + unsigned int key = *(unsigned int *)txn->cache_hash; |
759 | |
760 | /* Don't cache if the response came from a cache */ |
761 | if ((obj_type(s->target) == OBJ_TYPE_APPLET) && |
762 | @@ -420,6 +420,10 @@ enum act_return http_action_store_cache(struct act_rule *rule, struct proxy *px, |
763 | if (txn->meth != HTTP_METH_GET) |
764 | goto out; |
765 | |
766 | + /* cache key was not computed */ |
767 | + if (!key) |
768 | + goto out; |
769 | + |
770 | /* cache only 200 status code */ |
771 | if (txn->status != 200) |
772 | goto out; |
773 | @@ -478,7 +482,7 @@ enum act_return http_action_store_cache(struct act_rule *rule, struct proxy *px, |
774 | |
775 | cache_ctx->first_block = first; |
776 | |
777 | - object->eb.key = (*(unsigned int *)&txn->cache_hash); |
778 | + object->eb.key = key; |
779 | memcpy(object->hash, txn->cache_hash, sizeof(object->hash)); |
780 | /* Insert the node later on caching success */ |
781 | |
782 | diff --git a/src/cfgparse.c b/src/cfgparse.c |
783 | index 94f2963..c178538 100644 |
784 | --- a/src/cfgparse.c |
785 | +++ b/src/cfgparse.c |
786 | @@ -613,16 +613,20 @@ int parse_process_number(const char *arg, unsigned long *proc, int *autoinc, cha |
787 | else if (strcmp(arg, "even") == 0) |
788 | *proc |= (~0UL/3UL) << 1; /* 0xAAA...AAA */ |
789 | else { |
790 | - char *dash; |
791 | + const char *p, *dash = NULL; |
792 | unsigned int low, high; |
793 | |
794 | - if (!isdigit((int)*arg)) { |
795 | - memprintf(err, "'%s' is not a valid number.\n", arg); |
796 | - return -1; |
797 | + for (p = arg; *p; p++) { |
798 | + if (*p == '-' && !dash) |
799 | + dash = p; |
800 | + else if (!isdigit((int)*p)) { |
801 | + memprintf(err, "'%s' is not a valid number/range.", arg); |
802 | + return -1; |
803 | + } |
804 | } |
805 | |
806 | low = high = str2uic(arg); |
807 | - if ((dash = strchr(arg, '-')) != NULL) |
808 | + if (dash) |
809 | high = ((!*(dash+1)) ? LONGBITS : str2uic(dash + 1)); |
810 | |
811 | if (high < low) { |
812 | @@ -2844,7 +2848,10 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm) |
813 | |
814 | if (defproxy.url_param_name) |
815 | curproxy->url_param_name = strdup(defproxy.url_param_name); |
816 | - curproxy->url_param_len = defproxy.url_param_len; |
817 | + curproxy->url_param_len = defproxy.url_param_len; |
818 | + curproxy->uri_whole = defproxy.uri_whole; |
819 | + curproxy->uri_len_limit = defproxy.uri_len_limit; |
820 | + curproxy->uri_dirs_depth1 = defproxy.uri_dirs_depth1; |
821 | |
822 | if (defproxy.hh_name) |
823 | curproxy->hh_name = strdup(defproxy.hh_name); |
824 | @@ -7648,9 +7655,9 @@ int check_config_validity() |
825 | /* detect and address thread affinity inconsistencies */ |
826 | nbproc = 0; |
827 | if (bind_conf->bind_proc) |
828 | - nbproc = my_ffsl(bind_conf->bind_proc); |
829 | + nbproc = my_ffsl(bind_conf->bind_proc) - 1; |
830 | |
831 | - mask = bind_conf->bind_thread[nbproc - 1]; |
832 | + mask = bind_conf->bind_thread[nbproc]; |
833 | if (mask && !(mask & all_threads_mask)) { |
834 | unsigned long new_mask = 0; |
835 | |
836 | @@ -7996,6 +8003,11 @@ int check_config_validity() |
837 | curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id); |
838 | cfgerr++; |
839 | } |
840 | + else if (curproxy->bind_proc & ~target->bind_proc) { |
841 | + ha_alert("Proxy '%s': stick-table '%s' referenced 'stick-store' rule not present on all processes covered by proxy '%s'.\n", |
842 | + curproxy->id, target->id, curproxy->id); |
843 | + cfgerr++; |
844 | + } |
845 | else { |
846 | free((void *)mrule->table.name); |
847 | mrule->table.t = &(target->table); |
848 | @@ -8029,6 +8041,11 @@ int check_config_validity() |
849 | curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id); |
850 | cfgerr++; |
851 | } |
852 | + else if (curproxy->bind_proc & ~target->bind_proc) { |
853 | + ha_alert("Proxy '%s': stick-table '%s' referenced 'stick-store' rule not present on all processes covered by proxy '%s'.\n", |
854 | + curproxy->id, target->id, curproxy->id); |
855 | + cfgerr++; |
856 | + } |
857 | else { |
858 | free((void *)mrule->table.name); |
859 | mrule->table.t = &(target->table); |
860 | @@ -8829,6 +8846,33 @@ out_uri_auth_compat: |
861 | } |
862 | } |
863 | } |
864 | + |
865 | + /* initialize idle conns lists */ |
866 | + for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) { |
867 | + int i; |
868 | + |
869 | + newsrv->priv_conns = calloc(global.nbthread, sizeof(*newsrv->priv_conns)); |
870 | + newsrv->idle_conns = calloc(global.nbthread, sizeof(*newsrv->idle_conns)); |
871 | + newsrv->safe_conns = calloc(global.nbthread, sizeof(*newsrv->safe_conns)); |
872 | + |
873 | + if (!newsrv->priv_conns || !newsrv->idle_conns || !newsrv->safe_conns) { |
874 | + free(newsrv->safe_conns); newsrv->safe_conns = NULL; |
875 | + free(newsrv->idle_conns); newsrv->idle_conns = NULL; |
876 | + free(newsrv->priv_conns); newsrv->priv_conns = NULL; |
877 | + ha_alert("parsing [%s:%d] : failed to allocate idle connections for server '%s'.\n", |
878 | + newsrv->conf.file, newsrv->conf.line, newsrv->id); |
879 | + cfgerr++; |
880 | + continue; |
881 | + } |
882 | + |
883 | + for (i = 0; i < global.nbthread; i++) { |
884 | + LIST_INIT(&newsrv->priv_conns[i]); |
885 | + LIST_INIT(&newsrv->idle_conns[i]); |
886 | + LIST_INIT(&newsrv->safe_conns[i]); |
887 | + } |
888 | + |
889 | + LIST_INIT(&newsrv->update_status); |
890 | + } |
891 | } |
892 | |
893 | /***********************************************************/ |
894 | diff --git a/src/checks.c b/src/checks.c |
895 | index 74958b2..e04f114 100644 |
896 | --- a/src/checks.c |
897 | +++ b/src/checks.c |
898 | @@ -1403,12 +1403,13 @@ static int wake_srv_chk(struct conn_stream *cs) |
899 | } |
900 | |
901 | if (check->result != CHK_RES_UNKNOWN) { |
902 | - /* We're here because nobody wants to handle the error, so we |
903 | - * sure want to abort the hard way. |
904 | - */ |
905 | + /* Check complete or aborted. If connection not yet closed do it |
906 | + * now and wake the check task up to be sure the result is |
907 | + * handled ASAP. */ |
908 | conn_sock_drain(conn); |
909 | cs_close(cs); |
910 | ret = -1; |
911 | + task_wakeup(check->task, TASK_WOKEN_IO); |
912 | } |
913 | |
914 | HA_SPIN_UNLOCK(SERVER_LOCK, &check->server->lock); |
915 | diff --git a/src/flt_spoe.c b/src/flt_spoe.c |
916 | index 4009c2a..e445388 100644 |
917 | --- a/src/flt_spoe.c |
918 | +++ b/src/flt_spoe.c |
919 | @@ -170,8 +170,10 @@ spoe_release_agent(struct spoe_agent *agent) |
920 | LIST_DEL(&grp->list); |
921 | spoe_release_group(grp); |
922 | } |
923 | - for (i = 0; i < global.nbthread; ++i) |
924 | - HA_SPIN_DESTROY(&agent->rt[i].lock); |
925 | + if (agent->rt) { |
926 | + for (i = 0; i < global.nbthread; ++i) |
927 | + HA_SPIN_DESTROY(&agent->rt[i].lock); |
928 | + } |
929 | free(agent->rt); |
930 | free(agent); |
931 | } |
932 | @@ -444,7 +446,7 @@ spoe_prepare_hahello_frame(struct appctx *appctx, char *frame, size_t size) |
933 | if (agent != NULL && (agent->flags & SPOE_FL_RCV_FRAGMENTATION)) { |
934 | if (chk->len) chk->str[chk->len++] = ','; |
935 | memcpy(chk->str+chk->len, "fragmentation", 13); |
936 | - chk->len += 5; |
937 | + chk->len += 13; |
938 | } |
939 | if (spoe_encode_buffer(chk->str, chk->len, &p, end) == -1) |
940 | goto too_big; |
941 | @@ -817,10 +819,14 @@ spoe_handle_agenthello_frame(struct appctx *appctx, char *frame, size_t size) |
942 | SPOE_APPCTX(appctx)->status_code = SPOE_FRM_ERR_NO_FRAME_SIZE; |
943 | return -1; |
944 | } |
945 | - if ((flags & SPOE_APPCTX_FL_PIPELINING) && !(agent->flags & SPOE_FL_PIPELINING)) |
946 | - flags &= ~SPOE_APPCTX_FL_PIPELINING; |
947 | - if ((flags & SPOE_APPCTX_FL_ASYNC) && !(agent->flags & SPOE_FL_ASYNC)) |
948 | - flags &= ~SPOE_APPCTX_FL_ASYNC; |
949 | + if (!agent) |
950 | + flags &= ~(SPOE_APPCTX_FL_PIPELINING|SPOE_APPCTX_FL_ASYNC); |
951 | + else { |
952 | + if ((flags & SPOE_APPCTX_FL_PIPELINING) && !(agent->flags & SPOE_FL_PIPELINING)) |
953 | + flags &= ~SPOE_APPCTX_FL_PIPELINING; |
954 | + if ((flags & SPOE_APPCTX_FL_ASYNC) && !(agent->flags & SPOE_FL_ASYNC)) |
955 | + flags &= ~SPOE_APPCTX_FL_ASYNC; |
956 | + } |
957 | |
958 | SPOE_APPCTX(appctx)->version = (unsigned int)vsn; |
959 | SPOE_APPCTX(appctx)->max_frame_size = (unsigned int)max_frame_size; |
960 | @@ -2881,6 +2887,7 @@ spoe_check(struct proxy *px, struct flt_conf *fconf) |
961 | struct flt_conf *f; |
962 | struct spoe_config *conf = fconf->conf; |
963 | struct proxy *target; |
964 | + int i; |
965 | |
966 | /* Check all SPOE filters for proxy <px> to be sure all SPOE agent names |
967 | * are uniq */ |
968 | @@ -2918,6 +2925,34 @@ spoe_check(struct proxy *px, struct flt_conf *fconf) |
969 | return 1; |
970 | } |
971 | |
972 | + if (px->bind_proc & ~target->bind_proc) { |
973 | + ha_alert("Proxy %s : backend '%s' used by SPOE agent '%s' declared" |
974 | + " at %s:%d does not cover all of its processes.\n", |
975 | + px->id, target->id, conf->agent->id, |
976 | + conf->agent->conf.file, conf->agent->conf.line); |
977 | + return 1; |
978 | + } |
979 | + |
980 | + /* finish per-thread agent initialization */ |
981 | + if (global.nbthread == 1) |
982 | + conf->agent->flags |= SPOE_FL_ASYNC; |
983 | + |
984 | + if ((curagent->rt = calloc(global.nbthread, sizeof(*curagent->rt))) == NULL) { |
985 | + ha_alert("Proxy %s : out of memory initializing SPOE agent '%s' declared at %s:%d.\n", |
986 | + px->id, conf->agent->id, conf->agent->conf.file, conf->agent->conf.line); |
987 | + return 1; |
988 | + } |
989 | + for (i = 0; i < global.nbthread; ++i) { |
990 | + curagent->rt[i].frame_size = curagent->max_frame_size; |
991 | + curagent->rt[i].applets_act = 0; |
992 | + curagent->rt[i].applets_idle = 0; |
993 | + curagent->rt[i].sending_rate = 0; |
994 | + LIST_INIT(&curagent->rt[i].applets); |
995 | + LIST_INIT(&curagent->rt[i].sending_queue); |
996 | + LIST_INIT(&curagent->rt[i].waiting_queue); |
997 | + HA_SPIN_INIT(&curagent->rt[i].lock); |
998 | + } |
999 | + |
1000 | free(conf->agent->b.name); |
1001 | conf->agent->b.name = NULL; |
1002 | conf->agent->b.be = target; |
1003 | @@ -3196,8 +3231,6 @@ cfg_parse_spoe_agent(const char *file, int linenum, char **args, int kwm) |
1004 | curagent->var_pfx = NULL; |
1005 | curagent->var_on_error = NULL; |
1006 | curagent->flags = (SPOE_FL_PIPELINING | SPOE_FL_SND_FRAGMENTATION); |
1007 | - if (global.nbthread == 1) |
1008 | - curagent->flags |= SPOE_FL_ASYNC; |
1009 | curagent->cps_max = 0; |
1010 | curagent->eps_max = 0; |
1011 | curagent->max_frame_size = MAX_FRAME_SIZE; |
1012 | @@ -3208,22 +3241,6 @@ cfg_parse_spoe_agent(const char *file, int linenum, char **args, int kwm) |
1013 | LIST_INIT(&curagent->events[i]); |
1014 | LIST_INIT(&curagent->groups); |
1015 | LIST_INIT(&curagent->messages); |
1016 | - |
1017 | - if ((curagent->rt = calloc(global.nbthread, sizeof(*curagent->rt))) == NULL) { |
1018 | - ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum); |
1019 | - err_code |= ERR_ALERT | ERR_ABORT; |
1020 | - goto out; |
1021 | - } |
1022 | - for (i = 0; i < global.nbthread; ++i) { |
1023 | - curagent->rt[i].frame_size = curagent->max_frame_size; |
1024 | - curagent->rt[i].applets_act = 0; |
1025 | - curagent->rt[i].applets_idle = 0; |
1026 | - curagent->rt[i].sending_rate = 0; |
1027 | - LIST_INIT(&curagent->rt[i].applets); |
1028 | - LIST_INIT(&curagent->rt[i].sending_queue); |
1029 | - LIST_INIT(&curagent->rt[i].waiting_queue); |
1030 | - HA_SPIN_INIT(&curagent->rt[i].lock); |
1031 | - } |
1032 | } |
1033 | else if (!strcmp(args[0], "use-backend")) { |
1034 | if (!*args[1]) { |
1035 | diff --git a/src/haproxy.c b/src/haproxy.c |
1036 | index ad6d069..6836762 100644 |
1037 | --- a/src/haproxy.c |
1038 | +++ b/src/haproxy.c |
1039 | @@ -2155,6 +2155,7 @@ void deinit(void) |
1040 | } |
1041 | |
1042 | deinit_tcp_rules(&p->tcp_req.inspect_rules); |
1043 | + deinit_tcp_rules(&p->tcp_rep.inspect_rules); |
1044 | deinit_tcp_rules(&p->tcp_req.l4_rules); |
1045 | |
1046 | deinit_stick_rules(&p->storersp_rules); |
1047 | diff --git a/src/hlua.c b/src/hlua.c |
1048 | index efeee31..93cb86d 100644 |
1049 | --- a/src/hlua.c |
1050 | +++ b/src/hlua.c |
1051 | @@ -7984,9 +7984,9 @@ void hlua_init(void) |
1052 | socket_ssl.obj_type = OBJ_TYPE_SERVER; |
1053 | LIST_INIT(&socket_ssl.actconns); |
1054 | LIST_INIT(&socket_ssl.pendconns); |
1055 | - socket_tcp.priv_conns = NULL; |
1056 | - socket_tcp.idle_conns = NULL; |
1057 | - socket_tcp.safe_conns = NULL; |
1058 | + socket_ssl.priv_conns = NULL; |
1059 | + socket_ssl.idle_conns = NULL; |
1060 | + socket_ssl.safe_conns = NULL; |
1061 | socket_ssl.next_state = SRV_ST_RUNNING; /* early server setup */ |
1062 | socket_ssl.last_change = 0; |
1063 | socket_ssl.id = "LUA-SSL-CONN"; |
1064 | diff --git a/src/hpack-dec.c b/src/hpack-dec.c |
1065 | index 99d40f9..3fd4224 100644 |
1066 | --- a/src/hpack-dec.c |
1067 | +++ b/src/hpack-dec.c |
1068 | @@ -213,6 +213,12 @@ int hpack_decode_frame(struct hpack_dht *dht, const uint8_t *raw, uint32_t len, |
1069 | ret = -HPACK_ERR_TRUNCATED; |
1070 | goto leave; |
1071 | } |
1072 | + |
1073 | + if (idx > dht->size) { |
1074 | + hpack_debug_printf("##ERR@%d##\n", __LINE__); |
1075 | + ret = -HPACK_ERR_INVALID_ARGUMENT; |
1076 | + goto leave; |
1077 | + } |
1078 | continue; |
1079 | } |
1080 | else if (!(*raw & (*raw - 0x10))) { |
1081 | diff --git a/src/mux_h2.c b/src/mux_h2.c |
1082 | index b57ba6f..b2f3096 100644 |
1083 | --- a/src/mux_h2.c |
1084 | +++ b/src/mux_h2.c |
1085 | @@ -548,12 +548,15 @@ static inline __maybe_unused void h2c_error(struct h2c *h2c, enum h2_err err) |
1086 | h2c->st0 = H2_CS_ERROR; |
1087 | } |
1088 | |
1089 | -/* marks an error on the stream */ |
1090 | +/* marks an error on the stream. It may also update an already closed stream |
1091 | + * (e.g. to report an error after an RST was received). |
1092 | + */ |
1093 | static inline __maybe_unused void h2s_error(struct h2s *h2s, enum h2_err err) |
1094 | { |
1095 | - if (h2s->st > H2_SS_IDLE && h2s->st < H2_SS_ERROR) { |
1096 | + if (h2s->id && h2s->st != H2_SS_ERROR) { |
1097 | h2s->errcode = err; |
1098 | - h2s->st = H2_SS_ERROR; |
1099 | + if (h2s->st < H2_SS_ERROR) |
1100 | + h2s->st = H2_SS_ERROR; |
1101 | if (h2s->cs) |
1102 | h2s->cs->flags |= CS_FL_ERROR; |
1103 | } |
1104 | @@ -1140,6 +1143,14 @@ static void h2c_update_all_ws(struct h2c *h2c, int diff) |
1105 | while (node) { |
1106 | h2s = container_of(node, struct h2s, by_id); |
1107 | h2s->mws += diff; |
1108 | + |
1109 | + if (h2s->mws > 0 && (h2s->flags & H2_SF_BLK_SFCTL)) { |
1110 | + h2s->flags &= ~H2_SF_BLK_SFCTL; |
1111 | + if (h2s->cs && LIST_ISEMPTY(&h2s->list) && |
1112 | + (h2s->cs->flags & CS_FL_DATA_WR_ENA)) |
1113 | + LIST_ADDQ(&h2c->send_list, &h2s->list); |
1114 | + } |
1115 | + |
1116 | node = eb32_next(node); |
1117 | } |
1118 | } |
1119 | @@ -1766,7 +1777,11 @@ static int h2c_frt_handle_data(struct h2c *h2c, struct h2s *h2s) |
1120 | |
1121 | /* last frame */ |
1122 | if (h2c->dff & H2_F_DATA_END_STREAM) { |
1123 | - h2s->st = H2_SS_HREM; |
1124 | + if (h2s->st == H2_SS_OPEN) |
1125 | + h2s->st = H2_SS_HREM; |
1126 | + else |
1127 | + h2s_close(h2s); |
1128 | + |
1129 | h2s->flags |= H2_SF_ES_RCVD; |
1130 | } |
1131 | |
1132 | @@ -1891,10 +1906,14 @@ static void h2_process_demux(struct h2c *h2c) |
1133 | if (h2s->st == H2_SS_HREM && h2c->dft != H2_FT_WINDOW_UPDATE && |
1134 | h2c->dft != H2_FT_RST_STREAM && h2c->dft != H2_FT_PRIORITY) { |
1135 | /* RFC7540#5.1: any frame other than WU/PRIO/RST in |
1136 | - * this state MUST be treated as a stream error |
1137 | + * this state MUST be treated as a stream error. |
1138 | + * 6.2, 6.6 and 6.10 further mandate that HEADERS/ |
1139 | + * PUSH_PROMISE/CONTINUATION cause connection errors. |
1140 | */ |
1141 | - h2s_error(h2s, H2_ERR_STREAM_CLOSED); |
1142 | - h2c->st0 = H2_CS_FRAME_E; |
1143 | + if (h2_ft_bit(h2c->dft) & H2_FT_HDR_MASK) |
1144 | + h2c_error(h2c, H2_ERR_PROTOCOL_ERROR); |
1145 | + else |
1146 | + h2s_error(h2s, H2_ERR_STREAM_CLOSED); |
1147 | goto strm_err; |
1148 | } |
1149 | |
1150 | @@ -1910,7 +1929,7 @@ static void h2_process_demux(struct h2c *h2c) |
1151 | * Some frames have to be silently ignored as well. |
1152 | */ |
1153 | if (h2s->st == H2_SS_CLOSED && h2c->dsi) { |
1154 | - if (h2c->dft == H2_FT_HEADERS || h2c->dft == H2_FT_PUSH_PROMISE) { |
1155 | + if (h2_ft_bit(h2c->dft) & H2_FT_HDR_MASK) { |
1156 | /* #5.1.1: The identifier of a newly |
1157 | * established stream MUST be numerically |
1158 | * greater than all streams that the initiating |
1159 | @@ -1949,7 +1968,7 @@ static void h2_process_demux(struct h2c *h2c) |
1160 | * over which it ignores frames and treat frames that |
1161 | * arrive after this time as being in error. |
1162 | */ |
1163 | - if (!(h2s->flags & H2_SF_RST_SENT)) { |
1164 | + if (h2s->id && !(h2s->flags & H2_SF_RST_SENT)) { |
1165 | /* RFC7540#5.1:closed: any frame other than |
1166 | * PRIO/WU/RST in this state MUST be treated as |
1167 | * a connection error |
1168 | @@ -2561,7 +2580,6 @@ static void h2_detach(struct conn_stream *cs) |
1169 | if (eb_is_empty(&h2c->streams_by_id) && /* don't close if streams exist */ |
1170 | ((h2c->conn->flags & CO_FL_ERROR) || /* errors close immediately */ |
1171 | (h2c->st0 >= H2_CS_ERROR && !h2c->task) || /* a timeout stroke earlier */ |
1172 | - (h2c->flags & (H2_CF_GOAWAY_FAILED | H2_CF_GOAWAY_SENT)) || |
1173 | (!h2c->mbuf->o && /* mux buffer empty, also process clean events below */ |
1174 | (conn_xprt_read0_pending(h2c->conn) || |
1175 | (h2c->last_sid >= 0 && h2c->max_id >= h2c->last_sid))))) { |
1176 | @@ -2588,11 +2606,17 @@ static void h2_shutr(struct conn_stream *cs, enum cs_shr_mode mode) |
1177 | if (h2s->st == H2_SS_HLOC || h2s->st == H2_SS_ERROR || h2s->st == H2_SS_CLOSED) |
1178 | return; |
1179 | |
1180 | - /* if no outgoing data was seen on this stream, it means it was |
1181 | - * closed with a "tcp-request content" rule that is normally |
1182 | - * used to kill the connection ASAP (eg: limit abuse). In this |
1183 | - * case we send a goaway to close the connection. |
1184 | + /* a connstream may require us to immediately kill the whole connection |
1185 | + * for example because of a "tcp-request content reject" rule that is |
1186 | + * normally used to limit abuse. In this case we schedule a goaway to |
1187 | + * close the connection. |
1188 | */ |
1189 | + if ((h2s->cs->flags & CS_FL_KILL_CONN) && |
1190 | + !(h2s->h2c->flags & (H2_CF_GOAWAY_SENT|H2_CF_GOAWAY_FAILED))) { |
1191 | + h2c_error(h2s->h2c, H2_ERR_ENHANCE_YOUR_CALM); |
1192 | + h2s_error(h2s, H2_ERR_ENHANCE_YOUR_CALM); |
1193 | + } |
1194 | + |
1195 | if (!(h2s->flags & H2_SF_RST_SENT) && |
1196 | h2s_send_rst_stream(h2s->h2c, h2s) <= 0) |
1197 | goto add_to_list; |
1198 | @@ -2635,11 +2659,17 @@ static void h2_shutw(struct conn_stream *cs, enum cs_shw_mode mode) |
1199 | else |
1200 | h2s->st = H2_SS_HLOC; |
1201 | } else { |
1202 | - /* if no outgoing data was seen on this stream, it means it was |
1203 | - * closed with a "tcp-request content" rule that is normally |
1204 | - * used to kill the connection ASAP (eg: limit abuse). In this |
1205 | - * case we send a goaway to close the connection. |
1206 | + /* a connstream may require us to immediately kill the whole connection |
1207 | + * for example because of a "tcp-request content reject" rule that is |
1208 | + * normally used to limit abuse. In this case we schedule a goaway to |
1209 | + * close the connection. |
1210 | */ |
1211 | + if ((h2s->cs->flags & CS_FL_KILL_CONN) && |
1212 | + !(h2s->h2c->flags & (H2_CF_GOAWAY_SENT|H2_CF_GOAWAY_FAILED))) { |
1213 | + h2c_error(h2s->h2c, H2_ERR_ENHANCE_YOUR_CALM); |
1214 | + h2s_error(h2s, H2_ERR_ENHANCE_YOUR_CALM); |
1215 | + } |
1216 | + |
1217 | if (!(h2s->flags & H2_SF_RST_SENT) && |
1218 | h2s_send_rst_stream(h2s->h2c, h2s) <= 0) |
1219 | goto add_to_list; |
1220 | diff --git a/src/proto_http.c b/src/proto_http.c |
1221 | index 7e4a835..efd318e 100644 |
1222 | --- a/src/proto_http.c |
1223 | +++ b/src/proto_http.c |
1224 | @@ -3935,7 +3935,8 @@ int http_process_request(struct stream *s, struct channel *req, int an_bit) |
1225 | * that parameter. This will be done in another analyser. |
1226 | */ |
1227 | if (!(s->flags & (SF_ASSIGNED|SF_DIRECT)) && |
1228 | - s->txn->meth == HTTP_METH_POST && s->be->url_param_name != NULL && |
1229 | + s->txn->meth == HTTP_METH_POST && |
1230 | + (s->be->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_PH && |
1231 | (msg->flags & (HTTP_MSGF_CNT_LEN|HTTP_MSGF_TE_CHNK))) { |
1232 | channel_dont_connect(req); |
1233 | req->analysers |= AN_REQ_HTTP_BODY; |
1234 | @@ -8210,6 +8211,7 @@ void http_init_txn(struct stream *s) |
1235 | |
1236 | txn->flags = 0; |
1237 | txn->status = -1; |
1238 | + *(unsigned int *)txn->cache_hash = 0; |
1239 | |
1240 | txn->cookie_first_date = 0; |
1241 | txn->cookie_last_date = 0; |
1242 | @@ -12106,6 +12108,7 @@ enum act_parse_ret parse_http_set_status(const char **args, int *orig_arg, struc |
1243 | enum act_return http_action_reject(struct act_rule *rule, struct proxy *px, |
1244 | struct session *sess, struct stream *s, int flags) |
1245 | { |
1246 | + si_must_kill_conn(chn_prod(&s->req)); |
1247 | channel_abort(&s->req); |
1248 | channel_abort(&s->res); |
1249 | s->req.analysers = 0; |
1250 | diff --git a/src/sample.c b/src/sample.c |
1251 | index 139d976..4c6b99d 100644 |
1252 | --- a/src/sample.c |
1253 | +++ b/src/sample.c |
1254 | @@ -1261,6 +1261,13 @@ int smp_resolve_args(struct proxy *p) |
1255 | break; |
1256 | } |
1257 | |
1258 | + if (p->bind_proc & ~px->bind_proc) { |
1259 | + ha_alert("parsing [%s:%d] : stick-table '%s' not present on all processes covered by proxy '%s'.\n", |
1260 | + cur->file, cur->line, px->id, p->id); |
1261 | + cfgerr++; |
1262 | + break; |
1263 | + } |
1264 | + |
1265 | free(arg->data.str.str); |
1266 | arg->data.str.str = NULL; |
1267 | arg->unresolved = 0; |
1268 | diff --git a/src/server.c b/src/server.c |
1269 | index a86db3d..0dded5b 100644 |
1270 | --- a/src/server.c |
1271 | +++ b/src/server.c |
1272 | @@ -1534,7 +1534,6 @@ static void srv_settings_cpy(struct server *srv, struct server *src, int srv_tmp |
1273 | static struct server *new_server(struct proxy *proxy) |
1274 | { |
1275 | struct server *srv; |
1276 | - int i; |
1277 | |
1278 | srv = calloc(1, sizeof *srv); |
1279 | if (!srv) |
1280 | @@ -1545,21 +1544,6 @@ static struct server *new_server(struct proxy *proxy) |
1281 | LIST_INIT(&srv->actconns); |
1282 | LIST_INIT(&srv->pendconns); |
1283 | |
1284 | - if ((srv->priv_conns = calloc(global.nbthread, sizeof(*srv->priv_conns))) == NULL) |
1285 | - goto free_srv; |
1286 | - if ((srv->idle_conns = calloc(global.nbthread, sizeof(*srv->idle_conns))) == NULL) |
1287 | - goto free_priv_conns; |
1288 | - if ((srv->safe_conns = calloc(global.nbthread, sizeof(*srv->safe_conns))) == NULL) |
1289 | - goto free_idle_conns; |
1290 | - |
1291 | - for (i = 0; i < global.nbthread; i++) { |
1292 | - LIST_INIT(&srv->priv_conns[i]); |
1293 | - LIST_INIT(&srv->idle_conns[i]); |
1294 | - LIST_INIT(&srv->safe_conns[i]); |
1295 | - } |
1296 | - |
1297 | - LIST_INIT(&srv->update_status); |
1298 | - |
1299 | srv->next_state = SRV_ST_RUNNING; /* early server setup */ |
1300 | srv->last_change = now.tv_sec; |
1301 | |
1302 | @@ -1572,14 +1556,6 @@ static struct server *new_server(struct proxy *proxy) |
1303 | srv->xprt = srv->check.xprt = srv->agent.xprt = xprt_get(XPRT_RAW); |
1304 | |
1305 | return srv; |
1306 | - |
1307 | - free_idle_conns: |
1308 | - free(srv->idle_conns); |
1309 | - free_priv_conns: |
1310 | - free(srv->priv_conns); |
1311 | - free_srv: |
1312 | - free(srv); |
1313 | - return NULL; |
1314 | } |
1315 | |
1316 | /* |
1317 | @@ -2843,16 +2819,37 @@ static void srv_update_state(struct server *srv, int version, char **params) |
1318 | HA_SPIN_LOCK(SERVER_LOCK, &srv->lock); |
1319 | /* recover operational state and apply it to this server |
1320 | * and all servers tracking this one */ |
1321 | + srv->check.health = srv_check_health; |
1322 | switch (srv_op_state) { |
1323 | case SRV_ST_STOPPED: |
1324 | srv->check.health = 0; |
1325 | srv_set_stopped(srv, "changed from server-state after a reload", NULL); |
1326 | break; |
1327 | case SRV_ST_STARTING: |
1328 | + /* If rise == 1 there is no STARTING state, let's switch to |
1329 | + * RUNNING |
1330 | + */ |
1331 | + if (srv->check.rise == 1) { |
1332 | + srv->check.health = srv->check.rise + srv->check.fall - 1; |
1333 | + srv_set_running(srv, "", NULL); |
1334 | + break; |
1335 | + } |
1336 | + if (srv->check.health < 1 || srv->check.health >= srv->check.rise) |
1337 | + srv->check.health = srv->check.rise - 1; |
1338 | srv->next_state = srv_op_state; |
1339 | break; |
1340 | case SRV_ST_STOPPING: |
1341 | - srv->check.health = srv->check.rise + srv->check.fall - 1; |
1342 | + /* If fall == 1 there is no STOPPING state, let's switch to |
1343 | + * STOPPED |
1344 | + */ |
1345 | + if (srv->check.fall == 1) { |
1346 | + srv->check.health = 0; |
1347 | + srv_set_stopped(srv, "changed from server-state after a reload", NULL); |
1348 | + break; |
1349 | + } |
1350 | + if (srv->check.health < srv->check.rise || |
1351 | + srv->check.health > srv->check.rise + srv->check.fall - 2) |
1352 | + srv->check.health = srv->check.rise; |
1353 | srv_set_stopping(srv, "changed from server-state after a reload", NULL); |
1354 | break; |
1355 | case SRV_ST_RUNNING: |
1356 | @@ -2906,7 +2903,6 @@ static void srv_update_state(struct server *srv, int version, char **params) |
1357 | srv->last_change = date.tv_sec - srv_last_time_change; |
1358 | srv->check.status = srv_check_status; |
1359 | srv->check.result = srv_check_result; |
1360 | - srv->check.health = srv_check_health; |
1361 | |
1362 | /* Only case we want to apply is removing ENABLED flag which could have been |
1363 | * done by the "disable health" command over the stats socket |
1364 | diff --git a/src/ssl_sock.c b/src/ssl_sock.c |
1365 | index 24ccc4b..7736c32 100644 |
1366 | --- a/src/ssl_sock.c |
1367 | +++ b/src/ssl_sock.c |
1368 | @@ -1406,6 +1406,10 @@ void ssl_sock_infocbk(const SSL *ssl, int where, int ret) |
1369 | BIO *write_bio; |
1370 | (void)ret; /* shut gcc stupid warning */ |
1371 | |
1372 | +#ifndef SSL_OP_NO_RENEGOTIATION |
1373 | + /* Please note that BoringSSL defines this macro to zero so don't |
1374 | + * change this to #if and do not assign a default value to this macro! |
1375 | + */ |
1376 | if (where & SSL_CB_HANDSHAKE_START) { |
1377 | /* Disable renegotiation (CVE-2009-3555) */ |
1378 | if ((conn->flags & (CO_FL_CONNECTED | CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_CONNECTED) { |
1379 | @@ -1413,6 +1417,7 @@ void ssl_sock_infocbk(const SSL *ssl, int where, int ret) |
1380 | conn->err_code = CO_ER_SSL_RENEG; |
1381 | } |
1382 | } |
1383 | +#endif |
1384 | |
1385 | if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) { |
1386 | if (!(conn->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) { |
1387 | @@ -3806,6 +3811,11 @@ ssl_sock_initial_ctx(struct bind_conf *bind_conf) |
1388 | options |= SSL_OP_NO_TICKET; |
1389 | if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH) |
1390 | options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE; |
1391 | + |
1392 | +#ifdef SSL_OP_NO_RENEGOTIATION |
1393 | + options |= SSL_OP_NO_RENEGOTIATION; |
1394 | +#endif |
1395 | + |
1396 | SSL_CTX_set_options(ctx, options); |
1397 | |
1398 | #if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC) |
1399 | @@ -3821,6 +3831,10 @@ ssl_sock_initial_ctx(struct bind_conf *bind_conf) |
1400 | SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk); |
1401 | SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk); |
1402 | #elif (OPENSSL_VERSION_NUMBER >= 0x10101000L) |
1403 | + if (bind_conf->ssl_conf.early_data) { |
1404 | + SSL_CTX_set_options(ctx, SSL_OP_NO_ANTI_REPLAY); |
1405 | + SSL_CTX_set_max_early_data(ctx, global.tune.bufsize - global.tune.maxrewrite); |
1406 | + } |
1407 | SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL); |
1408 | SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk); |
1409 | #else |
1410 | @@ -7623,15 +7637,36 @@ static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px |
1411 | } |
1412 | |
1413 | keys_ref = malloc(sizeof(*keys_ref)); |
1414 | + if (!keys_ref) { |
1415 | + if (err) |
1416 | + memprintf(err, "'%s' : allocation error", args[cur_arg+1]); |
1417 | + return ERR_ALERT | ERR_FATAL; |
1418 | + } |
1419 | + |
1420 | keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(struct tls_sess_key)); |
1421 | + if (!keys_ref->tlskeys) { |
1422 | + free(keys_ref); |
1423 | + if (err) |
1424 | + memprintf(err, "'%s' : allocation error", args[cur_arg+1]); |
1425 | + return ERR_ALERT | ERR_FATAL; |
1426 | + } |
1427 | |
1428 | if ((f = fopen(args[cur_arg + 1], "r")) == NULL) { |
1429 | + free(keys_ref->tlskeys); |
1430 | + free(keys_ref); |
1431 | if (err) |
1432 | memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]); |
1433 | return ERR_ALERT | ERR_FATAL; |
1434 | } |
1435 | |
1436 | keys_ref->filename = strdup(args[cur_arg + 1]); |
1437 | + if (!keys_ref->filename) { |
1438 | + free(keys_ref->tlskeys); |
1439 | + free(keys_ref); |
1440 | + if (err) |
1441 | + memprintf(err, "'%s' : allocation error", args[cur_arg+1]); |
1442 | + return ERR_ALERT | ERR_FATAL; |
1443 | + } |
1444 | |
1445 | while (fgets(thisline, sizeof(thisline), f) != NULL) { |
1446 | int len = strlen(thisline); |
1447 | @@ -7643,6 +7678,9 @@ static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px |
1448 | thisline[--len] = 0; |
1449 | |
1450 | if (base64dec(thisline, len, (char *) (keys_ref->tlskeys + i % TLS_TICKETS_NO), sizeof(struct tls_sess_key)) != sizeof(struct tls_sess_key)) { |
1451 | + free(keys_ref->filename); |
1452 | + free(keys_ref->tlskeys); |
1453 | + free(keys_ref); |
1454 | if (err) |
1455 | memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1); |
1456 | fclose(f); |
1457 | @@ -7652,6 +7690,9 @@ static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px |
1458 | } |
1459 | |
1460 | if (i < TLS_TICKETS_NO) { |
1461 | + free(keys_ref->filename); |
1462 | + free(keys_ref->tlskeys); |
1463 | + free(keys_ref); |
1464 | if (err) |
1465 | memprintf(err, "'%s' : please supply at least %d keys in the tls-tickets-file", args[cur_arg+1], TLS_TICKETS_NO); |
1466 | fclose(f); |
1467 | diff --git a/src/stream.c b/src/stream.c |
1468 | index 507cd2f..f443cc7 100644 |
1469 | --- a/src/stream.c |
1470 | +++ b/src/stream.c |
1471 | @@ -339,6 +339,9 @@ static void stream_free(struct stream *s) |
1472 | offer_buffers(NULL, tasks_run_queue + applets_active_queue); |
1473 | } |
1474 | |
1475 | + pool_free(pool_head_uniqueid, s->unique_id); |
1476 | + s->unique_id = NULL; |
1477 | + |
1478 | hlua_ctx_destroy(s->hlua); |
1479 | s->hlua = NULL; |
1480 | if (s->txn) |
1481 | @@ -593,7 +596,8 @@ static int sess_update_st_con_tcp(struct stream *s) |
1482 | */ |
1483 | si->state = SI_ST_EST; |
1484 | si->err_type = SI_ET_DATA_ERR; |
1485 | - rep->flags |= CF_READ_ERROR | CF_WRITE_ERROR; |
1486 | + req->flags |= CF_WRITE_ERROR; |
1487 | + rep->flags |= CF_READ_ERROR; |
1488 | return 1; |
1489 | } |
1490 | si->exp = TICK_ETERNITY; |
1491 | diff --git a/src/stream_interface.c b/src/stream_interface.c |
1492 | index f17980a..47a100d 100644 |
1493 | --- a/src/stream_interface.c |
1494 | +++ b/src/stream_interface.c |
1495 | @@ -830,6 +830,9 @@ static void stream_int_shutr_conn(struct stream_interface *si) |
1496 | if (si->state != SI_ST_EST && si->state != SI_ST_CON) |
1497 | return; |
1498 | |
1499 | + if (si->flags & SI_FL_KILL_CONN) |
1500 | + cs->flags |= CS_FL_KILL_CONN; |
1501 | + |
1502 | if (si_oc(si)->flags & CF_SHUTW) { |
1503 | cs_close(cs); |
1504 | si->state = SI_ST_DIS; |
1505 | @@ -880,6 +883,9 @@ static void stream_int_shutw_conn(struct stream_interface *si) |
1506 | * However, if SI_FL_NOLINGER is explicitly set, we know there is |
1507 | * no risk so we close both sides immediately. |
1508 | */ |
1509 | + if (si->flags & SI_FL_KILL_CONN) |
1510 | + cs->flags |= CS_FL_KILL_CONN; |
1511 | + |
1512 | if (si->flags & SI_FL_ERR) { |
1513 | /* quick close, the socket is alredy shut anyway */ |
1514 | } |
1515 | @@ -914,6 +920,8 @@ static void stream_int_shutw_conn(struct stream_interface *si) |
1516 | /* we may have to close a pending connection, and mark the |
1517 | * response buffer as shutr |
1518 | */ |
1519 | + if (si->flags & SI_FL_KILL_CONN) |
1520 | + cs->flags |= CS_FL_KILL_CONN; |
1521 | cs_close(cs); |
1522 | /* fall through */ |
1523 | case SI_ST_CER: |
1524 | diff --git a/src/tcp_rules.c b/src/tcp_rules.c |
1525 | index feee441..72a7015 100644 |
1526 | --- a/src/tcp_rules.c |
1527 | +++ b/src/tcp_rules.c |
1528 | @@ -162,6 +162,7 @@ resume_execution: |
1529 | break; |
1530 | } |
1531 | else if (rule->action == ACT_ACTION_DENY) { |
1532 | + si_must_kill_conn(chn_prod(req)); |
1533 | channel_abort(req); |
1534 | channel_abort(&s->res); |
1535 | req->analysers = 0; |
1536 | @@ -340,6 +341,7 @@ resume_execution: |
1537 | break; |
1538 | } |
1539 | else if (rule->action == ACT_ACTION_DENY) { |
1540 | + si_must_kill_conn(chn_prod(rep)); |
1541 | channel_abort(rep); |
1542 | channel_abort(&s->req); |
1543 | rep->analysers = 0; |
1544 | @@ -357,6 +359,7 @@ resume_execution: |
1545 | } |
1546 | else if (rule->action == ACT_TCP_CLOSE) { |
1547 | chn_prod(rep)->flags |= SI_FL_NOLINGER | SI_FL_NOHALF; |
1548 | + si_must_kill_conn(chn_prod(rep)); |
1549 | si_shutr(chn_prod(rep)); |
1550 | si_shutw(chn_prod(rep)); |
1551 | break; |