]> git.ipfire.org Git - thirdparty/haproxy.git/log
thirdparty/haproxy.git
3 years agoMEDIUM: global: Add a "close-spread-time" option to spread soft-stop on time window
Remi Tricot-Le Breton [Fri, 8 Apr 2022 16:04:18 +0000 (18:04 +0200)] 
MEDIUM: global: Add a "close-spread-time" option to spread soft-stop on time window

The new 'close-spread-time' global option can be used to spread idle and
active HTTP connction closing after a SIGUSR1 signal is received. This
allows to limit bursts of reconnections when too many idle connections
are closed at once. Indeed, without this new mechanism, in case of
soft-stop, all the idle connections would be closed at once (after the
grace period is over), and all active HTTP connections would be closed
by appending a "Connection: close" header to the next response that goes
over it (or via a GOAWAY frame in case of HTTP2).

This patch adds the support of this new option for HTTP as well as HTTP2
connections. It works differently on active and idle connections.

On active connections, instead of sending systematically the GOAWAY
frame or adding the 'Connection: close' header like before once the
soft-stop has started, a random based on the remainder of the close
window is calculated, and depending on its result we could decide to
keep the connection alive. The random will be recalculated for any
subsequent request/response on this connection so the GOAWAY will still
end up being sent, but we might wait a few more round trips. This will
ensure that goaways are distributed along a longer time window than
before.

On idle connections, a random factor is used when determining the expire
field of the connection's task, which should naturally spread connection
closings on the time window (see h2c_update_timeout).

This feature request was described in GitHub issue #1614.
This patch should be backported to 2.5. It depends on "BUG/MEDIUM:
mux-h2: make use of http-request and keep-alive timeouts" which
refactorized the timeout management of HTTP2 connections.

3 years agoRevert "BUILD: opentracing: display warning in case of using OT_USE_VARS at compile...
Miroslav Zagorac [Wed, 9 Mar 2022 18:57:56 +0000 (19:57 +0100)] 
Revert "BUILD: opentracing: display warning in case of using OT_USE_VARS at compile time"

This reverts commit 6c9f7faa62a00a4d028704d7b11e290c83f8a49d.

This warning is no longer needed because source code can be compiled with
enabled support for OpenTracing context transfer via HAProxy variables.

This patch must be backported in 2.5.

3 years agoMAJOR: opentracing: reenable usage of vars to transmit opentracing context
Miroslav Zagorac [Wed, 9 Mar 2022 23:03:24 +0000 (00:03 +0100)] 
MAJOR: opentracing: reenable usage of vars to transmit opentracing context

Since commit 3a4bedccc ("MEDIUM: vars: replace the global name index with
a hash") the names of HAProxy variables are no longer saved, ie their
64-bit hashes are saved instead.

This is very convenient for the HAProxy itself, but for the OpenTracing
module it is a problem because the names of the variables are important
when transferring the OpenTracing context.  Namely, this context consists
of an unknown amount of data stored in a key-value format.  The number
of these data (and the name of the variable used for this purpose) is
determined with the configuration of the OpenTracing filter, as well as
with the tracer used.  The two previous sentences seem to be in conflict,
but that is only so at first glance.  The function in the OpenTracing
filter used to read the context does not really know this, neither their
number nor its name.  The only thing that function actually knows is the
prefix of the variable names used for context transfer, and by that it
could find all the necessary data.  Of course, until the application of
the above-mentioned commit.

The problem is solved in a very simple way: in a common variable that
the filter always knows its name, the names of all variables that are the
product of the OpenTracing context are saved.  The names of these context
variables can only be added to that common variable.  When that variable
is no longer needed (when we no longer need context), it is deleted.

The format for saving data to this common variable is as follows:
  +-----+---------------+-- .. --+-----+---------------+
  | len | variable name |        | len | variable name |
  +-----+---------------+-- .. --+-----+---------------+

The amount of memory space used to store the length of the name is 1 byte,
with a sign (the minus sign is provided for inactive records, but this is
not currently used).  This means that the maximum length of the variable
name to be saved is 127 characters, which is quite enough for use in the
filter.  The buffer size for such data storage is global.tune.bufsize.

This patch must be backported in 2.5.

3 years agoDEBUG: opentracing: display the contents of the err variable after setting
Miroslav Zagorac [Tue, 8 Mar 2022 00:21:04 +0000 (01:21 +0100)] 
DEBUG: opentracing: display the contents of the err variable after setting

A display of the contents of the err variable has been added to the
FLT_OT_ERR() macro, once it has been set.

This patch must be backported as far as 2.4.

3 years agoCLEANUP: opentracing: added FLT_OT_PARSE_INVALID_enum enum
Miroslav Zagorac [Mon, 7 Mar 2022 12:14:16 +0000 (13:14 +0100)] 
CLEANUP: opentracing: added FLT_OT_PARSE_INVALID_enum enum

It's always good to replace "hard-coded" values with something that looks
less "hard-coded" (even though that doesn't change anything in the code).
This is done here using FLT_OT_PARSE_INVALID_enum enum.

This patch must be backported as far as 2.4.

3 years agoDEBUG: opentracing: show return values of all functions in the debug output
Miroslav Zagorac [Fri, 4 Mar 2022 08:56:00 +0000 (09:56 +0100)] 
DEBUG: opentracing: show return values of all functions in the debug output

If the OpenTracing filter is compiled using the 'OT_DEBUG=1' option, then
log messages are printed to stderr when the filter is running.  In the log
one can then find (among other things) the order in which the function is
called and the value that the function returns (if it is not a void type).

Prior to applying this patch, no value returned by a function was logged.

Log output example:
  [ 1]    0.038807 [OT]: flt_ot_init_per_thread(0x56365bd45ec0, 0x56365bd48210) {
  [ 1]    0.038807 [OT]:    ot_start(0x56365bd58920, 0x56365bd4e3a0, 0x7f561acba168:(nil)) {
  [ 1]    0.038807 [OT]:    } = 0
  [ 1]    0.038807 [OT]: } = 0

This patch must be backported as far as 2.4.

3 years agoMINOR: opentracing: improved normalization of context variable names
Miroslav Zagorac [Tue, 1 Mar 2022 23:15:23 +0000 (00:15 +0100)] 
MINOR: opentracing: improved normalization of context variable names

The flag_cpy parameter has been added to the flt_ot_normalize_name()
function, through which we can determine whether the function converts
special characters (which are part of that name) when copying a variable
name.

This patch must be backported in 2.5.

3 years agoCLEANUP: opentracing: added variable to store variable length
Miroslav Zagorac [Tue, 1 Mar 2022 17:44:36 +0000 (18:44 +0100)] 
CLEANUP: opentracing: added variable to store variable length

The same variable should not be used to store multiple different results,
because it can be confusing.  Therefore, the var_name_len variable has
been added in several functions, in order to avoid the use of the retval
variable for several different purposes.

This patch must be backported as far as 2.4.

3 years agoCLEANUP: opentracing: added flt_ot_smp_init() function
Miroslav Zagorac [Tue, 1 Mar 2022 17:41:36 +0000 (18:41 +0100)] 
CLEANUP: opentracing: added flt_ot_smp_init() function

The flt_ot_smp_init() function has been added to make initializing the
sample structure easier.  The contents of the structure in question are
set in several places in the source of the OpenTracing filter, so it is
better to do this in one place.

This patch must be backported as far as 2.4.

3 years agoMINOR: opentracing: only takes the variables lock on shared entries
Miroslav Zagorac [Wed, 23 Feb 2022 17:15:56 +0000 (18:15 +0100)] 
MINOR: opentracing: only takes the variables lock on shared entries

Regarding commit #61ecf2838:
  There's no point taking the variables locks for sess/txn/req/res
  contexts since these ones always run inside the same thread anyway.

This patch must be backported in 2.5.

3 years agoRevert "MINOR: opentracing: change the scope of the variable 'ot.uuid' from 'sess...
Miroslav Zagorac [Wed, 23 Feb 2022 09:28:10 +0000 (10:28 +0100)] 
Revert "MINOR: opentracing: change the scope of the variable 'ot.uuid' from 'sess' to 'txn'"

This reverts commit 560c7b874aef5922199e36a7f31466af323f489f.

The ot.uuid variable should have the 'sess' scope because it is created
when an OpenTracing filter is attached to a stream.  After that, the
stream processing is started and on that occasion the contexts for the
variables that have the range 'txn' and 'req' are initialized.  This
means that we cannot use variables with the specified scopes before that
point.

This patch must be backported in 2.5.

3 years agoCLEANUP: opentracing: removed unused function flt_ot_var_get()
Miroslav Zagorac [Tue, 1 Mar 2022 17:39:18 +0000 (18:39 +0100)] 
CLEANUP: opentracing: removed unused function flt_ot_var_get()

The flt_ot_var_get() function is not used anywhere and is unnecessary
in the existing implementation of the OpenTracing filter.

This patch must be backported as far as 2.4.

3 years agoCLEANUP: opentracing: removed unused function flt_ot_var_unset()
Miroslav Zagorac [Tue, 1 Mar 2022 17:38:37 +0000 (18:38 +0100)] 
CLEANUP: opentracing: removed unused function flt_ot_var_unset()

The flt_ot_var_unset() function is not used anywhere and is unnecessary
in the existing implementation of the OpenTracing filter.

This patch must be backported as far as 2.4.

3 years agoDOC: opentracing: corrected comments in function descriptions
Miroslav Zagorac [Tue, 1 Mar 2022 18:18:34 +0000 (19:18 +0100)] 
DOC: opentracing: corrected comments in function descriptions

Several comments in the function descriptions have been corrected.

This patch must be backported as far as 2.4.

3 years agoEXAMPLES: opentracing: refined shell scripts for testing filter performance
Miroslav Zagorac [Wed, 9 Mar 2022 16:34:11 +0000 (17:34 +0100)] 
EXAMPLES: opentracing: refined shell scripts for testing filter performance

When calling the 'basename' command, the argument ${0} is enclosed in
quotation marks.  This is necessary if the path of the executable script
(contained in that argument) has "non-standard" elements, such as space
and the like.

Also, in the script 'test-speed.sh' the function sh_exit() has been added
for easier printing of messages at the end of execution.

This patch must be backported as far as 2.4.

3 years agoBUG/BUILD: opentracing: fixed OT_DEFINE variable setting
Miroslav Zagorac [Wed, 9 Mar 2022 18:59:15 +0000 (19:59 +0100)] 
BUG/BUILD: opentracing: fixed OT_DEFINE variable setting

In case of using parameter 'OT_USE_VARS=1', the value of the OT_DEFINE
variable is set incorrectly (i.e. the previous value was deleted and a
new one set instead of adding new content).

This patch must be backported in 2.5.

3 years agoBUG/MINOR: opentracing: setting the return value in function flt_ot_var_set()
Miroslav Zagorac [Tue, 1 Mar 2022 17:42:54 +0000 (18:42 +0100)] 
BUG/MINOR: opentracing: setting the return value in function flt_ot_var_set()

Function flt_ot_var_set() did not check whether the variable was
successfully set or not.  In case of failure, the value -1 is returned.

This patch must be backported as far as 2.4.

3 years agoMINOR: quic_tls: Make key update use of reusable cipher contexts
Frédéric Lécaille [Tue, 5 Apr 2022 14:28:38 +0000 (16:28 +0200)] 
MINOR: quic_tls: Make key update use of reusable cipher contexts

We modify the key update feature implementation to support reusable cipher contexts
as this is done for the other cipher contexts for packet decryption and encryption.
To do so we attach a context to the quic_tls_kp struct and initialize it each time
the underlying secret key is updated. Same thing when we rotate the secrets keys,
we rotate the contexts as the same time.

3 years agoMINOR: quic: Add short packet key phase bit values to traces
Frédéric Lécaille [Tue, 5 Apr 2022 13:29:14 +0000 (15:29 +0200)] 
MINOR: quic: Add short packet key phase bit values to traces

This is useful to diagnose key update related issues.

3 years agoCLEANUP: quic: Do not set any cipher/group from ssl_quic_initial_ctx()
Frédéric Lécaille [Tue, 5 Apr 2022 10:19:31 +0000 (12:19 +0200)] 
CLEANUP: quic: Do not set any cipher/group from ssl_quic_initial_ctx()

These settings are potentially cancelled by others setting initialization shared
with SSL sock bindings. This will have to be clarified when we will adapt the
QUIC bindings configuration.

3 years agoMINOR: quic_tls: Stop hardcoding cipher IV lengths
Frédéric Lécaille [Tue, 5 Apr 2022 10:18:46 +0000 (12:18 +0200)] 
MINOR: quic_tls: Stop hardcoding cipher IV lengths

For QUIC AEAD usage, the number of bytes for the IVs is always 12.

3 years agoMINOR: quic_tls: Add reusable cipher contexts to QUIC TLS contexts
Frédéric Lécaille [Tue, 5 Apr 2022 08:28:29 +0000 (10:28 +0200)] 
MINOR: quic_tls: Add reusable cipher contexts to QUIC TLS contexts

Add ->ctx new member field to quic_tls_secrets struct to store the cipher context
for each QUIC TLS context TX/RX parts.
Add quic_tls_rx_ctx_init() and quic_tls_tx_ctx_init() functions to initialize
these cipher context for RX and TX parts respectively.
Make qc_new_isecs() call these two functions to initialize the cipher contexts
of the Initial secrets. Same thing for ha_quic_set_encryption_secrets() to
initialize the cipher contexts of the subsequent derived secrets (ORTT, Handshake,
1RTT).
Modify quic_tls_decrypt() and quic_tls_encrypt() to always use the same cipher
context without allocating it each time they are called.

3 years agoBUG/MEDIUM: quic: Possible crash from quic_free_arngs()
Frédéric Lécaille [Mon, 4 Apr 2022 11:43:58 +0000 (13:43 +0200)] 
BUG/MEDIUM: quic: Possible crash from quic_free_arngs()

All quic_arng_node objects are allocated from "pool_head_quic_arng" memory pool.
They must be deallocated calling pool_free().

3 years agoBUG/MINOR: quic: set the source not the destination address on accept()
Willy Tarreau [Fri, 8 Apr 2022 12:34:31 +0000 (14:34 +0200)] 
BUG/MINOR: quic: set the source not the destination address on accept()

When a QUIC connection is accepted, the wrong field is set from the
client's source address, it's the destination instead of the source.
No backport needed.

3 years agoBUG/MEDIUM: mux-quic: properly release conn-stream on detach
Amaury Denoyelle [Fri, 8 Apr 2022 10:00:12 +0000 (12:00 +0200)] 
BUG/MEDIUM: mux-quic: properly release conn-stream on detach

On qc_detach(), the qcs must cleared the conn-stream context and set its
cs pointer to NULL. This prevents the qcs to point to a dangling
reference.

Without this, a SEGFAULT may occurs in qc_wake_some_streams() when
accessing an already detached conn-stream instance through a qcs.

Here is the SEGFAULT observed on haproxy.org.
 Program terminated with signal 11, Segmentation fault.
 1234                            else if (qcs->cs->data_cb->wake) {
 (gdb) p qcs.cs.data_cb
 $1 = (const struct data_cb *) 0x0

This can happens since the following patch :
 commit fe035eca3a24ea0f031fdcdad23809bea5de32e4
 MEDIUM: mux-quic: report errors on conn-streams

3 years agoCLEANUP: mux-quic: remove uneeded TODO in qc_detach
Amaury Denoyelle [Fri, 8 Apr 2022 09:58:55 +0000 (11:58 +0200)] 
CLEANUP: mux-quic: remove uneeded TODO in qc_detach

The stream mux buffering has been reworked since the introduction of the
struct qc_stream_desc. A qcs is now able to quickly release its buffer
to the quic-conn.

3 years agoBUG/MEDIUM: http-act: Don't replace URI if path is not found or invalid
Christopher Faulet [Fri, 8 Apr 2022 08:44:21 +0000 (10:44 +0200)] 
BUG/MEDIUM: http-act: Don't replace URI if path is not found or invalid

For replace-path, replace-pathq and replace-uri actions, we must take care
to not match on the selected element if it is not defined.

regex_exec_match2() function expects to be called with a defined
subject. However, if the request path is invalid or not found, the function
is called with a NULL subject, leading to a crash when compiled without the
PRCE/PCRE2 support.

For instance the following rules crashes HAProxy on a CONNECT request:

  http-request replace-path /short/(.) /\1

This patch must be backported as far as 2.0.

3 years agoBUG/MEDIUM: http-conv: Fix url_enc() to not crush const samples
Christopher Faulet [Fri, 8 Apr 2022 08:04:05 +0000 (10:04 +0200)] 
BUG/MEDIUM: http-conv: Fix url_enc() to not crush const samples

url_enc() encodes an input string by calling encode_string(). To do so, it
adds a trailing '\0' to the sample string. However it never restores the
sample string at the end. It is a problem for const samples. The sample
string may be in the middle of a buffer. For instance, the HTTP headers
values are concerned.

However, instead of modifying the sample string, it is easier to rely on
encode_chunk() function. It does the same but on a buffer.

This patch must be backported as far as 2.2.

3 years agoBUG/MINOR: http_client: Don't add input data on an empty request buffer
Christopher Faulet [Thu, 7 Apr 2022 08:47:07 +0000 (10:47 +0200)] 
BUG/MINOR: http_client: Don't add input data on an empty request buffer

When compiled in debug mode, a BUG_ON triggers an error when the payload is
fully transfered from the http-client buffer to the request channel
buffer. In fact, when channel_add_input() is called, the request buffer is
empty. So an error is reported when those data are directly forwarded,
because we try to add some output data on a buffer with no data.

To fix the bug, we must be sure to call channel_add_input() after the data
transfer.

The bug was introduced by the commit ccc7ee45f ("MINOR: httpclient: enable
request buffering"). So, this patch must be backported if the above commit
is backported.

3 years agoBUG/MEDIUM: mux-h1: Set outgoing message to DONE when payload length is reached
Christopher Faulet [Thu, 7 Apr 2022 08:29:38 +0000 (10:29 +0200)] 
BUG/MEDIUM: mux-h1: Set outgoing message to DONE when payload length is reached

When a message is sent, we can switch it state to MSG_DONE if all the
announced payload was processed. This way, if the EOM flag is not set on the
message when the last expected data block is processed, the message can
still be set to MSG_DONE state.

This bug is related to the previous ones. There is a design issue with the
HTX since the 2.4. When the EOM HTX block was replaced by a flag, I tried
hard to be sure the flag is always set with the last HTX block on a
message. It works pretty well for all messages received from a client or a
server. But for internal messages, it is not so simple. Because applets
cannot always properly handle the end of messages. So, there are some cases
where the EOM flag is set on an empty message.

As a workaround, for chunked messages, we can add an EOT HTX block. It does
the trick. But for messages with a content-length, there is no empty DATA
block. Thus, the only way to be sure the end of the message was reached in
this case is to detect it in the H1 multiplexr.

We already count the amount of data processed when the payload length is
announced. Thus, we must only switch the message in DONE state when last
bytes of the payload are received. Or when the EOM flag is received of
course.

This patch must be backported as far as 2.4.

3 years agoBUG/MEDIUM: promex: Be sure to never set EOM flag on an empty HTX message
Christopher Faulet [Thu, 7 Apr 2022 08:19:46 +0000 (10:19 +0200)] 
BUG/MEDIUM: promex: Be sure to never set EOM flag on an empty HTX message

It is the same bug than "BUG/MEDIUM: stats: Be sure to never set EOM flag on
an empty HTX message". We must be sure to set the EOM flag on a non empyt
message to be sure the mux on the client will properly handle
shutdowns. Otherwise, it may miss the end of the message and considers any
shutdown as an abort.

This patch must be backported as far as 2.4. On previous version there is
still the EOM HTX block.

3 years agoBUG/MEDIUM: hlua: Don't set EOM flag on an empty HTX message in HTTP applet
Christopher Faulet [Thu, 7 Apr 2022 08:07:18 +0000 (10:07 +0200)] 
BUG/MEDIUM: hlua: Don't set EOM flag on an empty HTX message in HTTP applet

In a lua HTTP applet, when the script is finished, we must be sure to not
set the EOM on an empty message. Otherwise, because there is no data to
send, the mux on the client side may miss the end of the message and
consider any shutdown as an abort.

See "UG/MEDIUM: stats: Be sure to never set EOM flag on an empty HTX
message" for details.

This patch must be backported as far as 2.4. On previous version there is
still the EOM HTX block.

3 years agoBUG/MEDIUM: stats: Be sure to never set EOM flag on an empty HTX message
Christopher Faulet [Thu, 7 Apr 2022 07:25:13 +0000 (09:25 +0200)] 
BUG/MEDIUM: stats: Be sure to never set EOM flag on an empty HTX message

During the last call to the stats I/O handle, it is possible to have nothing
to dump. It may happen for many reasons. For instance, all remaining proxies
are disabled or they don't match the specified scope. In HTML or in JSON, it
is not really an issue because there is a footer. So there are still some
data to push in the response channel buffer. In CSV, it is a problem because
there is no footer. It means it is possible to finish the response with no
payload at all in the HTX message. Thus, the EOM flag may be added on an
empty message. When this happens, a shutdown is performed on an empty HTX
message. Because there is nothing to send, the mux on the client side is not
notified that the message was properly finished and interprets the shutdown
as an abort.

The response is chunked. So an abort at this stage means the last CRLF is
never sent to the client. All data were sent but the message is invalid
because the response chunking is not finished. If the reponse is compressed,
because of a similar bug in the comppression filter, the compression is also
aborted and the content is truncated because some data a lost in the
compression filter.

It is design issue with the HTX. It must be addressed. And there is an
opportunity to do so with the recent conn-stream refactoring. It must be
carefully evaluated first. But it is possible. In the means time and to also
fix stable versions, to workaround the bug, a end-of-trailer HTX block is
systematically added at the end of the message when the EOM flag is set if
the HTX message is empty. This way, there are always some data to send when
the EOM flag is set.

Note that with a H2 client, it is only a problem when the response is
compressed.

This patch should fix the issue #1478. It must be backported as far as
2.4. On previous versions there is still the EOM block.

3 years agoBUG/MINOR: fcgi-app: Don't add C-L header on response to HEAD requests
Christopher Faulet [Wed, 6 Apr 2022 13:29:34 +0000 (15:29 +0200)] 
BUG/MINOR: fcgi-app: Don't add C-L header on response to HEAD requests

In the FCGI app, when a full response is received, if there is no
content-length and transfer-encoding headers, a content-length header is
automatically added. This avoid, as far as possible to chunk the
response. This trick was added because, most of time, scripts don"t add
those headers.

But this should not be performed for response to HEAD requests. Indeed, in
this case, there is no payload. If the payload size is not specified, we
must not added it by hand. Otherwise, a "content-length: 0" will always be
added while it is not the real payload size (unknown at this stage).

This patch should solve issue #1639. It must be backported as far as 2.2.

3 years agoMEDIUM: quic: report closing state for the MUX
Amaury Denoyelle [Wed, 6 Apr 2022 08:28:43 +0000 (10:28 +0200)] 
MEDIUM: quic: report closing state for the MUX

Define a new API to notify the MUX from the quic-conn when the
connection is about to be closed. This happens in the following cases :
- on idle timeout
- on CONNECTION_CLOSE emission or reception

The MUX wake callback is called on these conditions. The quic-conn
QUIC_FL_NOTIFY_CLOSE is set to only report once. On the MUX side,
connection flags CO_FL_SOCK_RD_SH|CO_FL_SOCK_WR_SH are set to interrupt
future emission/reception.

This patch is the counterpart to
  "MEDIUM: mux-quic: report CO_FL_ERROR on send".
Now the quic-conn is able to report its closing, which may be translated
by the MUX into a CO_FL_ERROR on the connection for the upper layer.
This allows the MUX to properly react to the QUIC closing mechanism for
both idle-timeout and closing/draining states.

3 years agoMEDIUM: mux-quic: report errors on conn-streams
Amaury Denoyelle [Wed, 6 Apr 2022 13:46:30 +0000 (15:46 +0200)] 
MEDIUM: mux-quic: report errors on conn-streams

Complete the error reporting. For each attached streams, if CO_FL_ERROR
is set, mark them with CS_FL_ERR_PENDING|CS_FL_ERROR. This will notify
the upper layer to trigger streams detach and release of the MUX.

This reporting is implemented in a new function qc_wake_some_streams(),
called by qc_wake(). This ensures that a lower-layer error is quickly
reported to the individual streams.

3 years agoMEDIUM: mux-quic: report CO_FL_ERROR on send
Amaury Denoyelle [Wed, 6 Apr 2022 14:13:09 +0000 (16:13 +0200)] 
MEDIUM: mux-quic: report CO_FL_ERROR on send

Mark the connection with CO_FL_ERROR on qc_send() if the socket Tx is
closed. This flag is used by the upper layer to order a close on the
MUX. This requires to check CO_FL_ERROR in qcc_is_dead() to process to
immediate MUX free when set.

The qc_wake() callback has been completed. Most notably, it now calls
qc_send() to report a possible CO_FL_ERROR. This is useful because
qc_wake() is called by the quic-conn on imminent closing.

Note that for the moment the error flag can never be set because the
quic-conn does not report when the Tx socket is closed. This will be
implemented in a following patch.

3 years agoMINOR: mux-quic: centralize send operations in qc_send
Amaury Denoyelle [Mon, 4 Apr 2022 14:36:34 +0000 (16:36 +0200)] 
MINOR: mux-quic: centralize send operations in qc_send

Regroup all features related to sending in qc_send(). This will be
useful when qc_send() will be called outside of the io-cb.

Currently, flow-control frames generation is now automatically
integrated in qc_send().

3 years agoMINOR: mux-quic: define is_active app-ops
Amaury Denoyelle [Fri, 1 Apr 2022 15:56:58 +0000 (17:56 +0200)] 
MINOR: mux-quic: define is_active app-ops

Add a new app layer operation is_active. This can be used by the MUX to
check if the connection can be considered as active or not. This is used
inside qcc_is_dead as a first check.

For example on HTTP/3, if there is at least one bidir client stream
opened the connection is active. This explicitly ignore the uni streams
used for control and qpack as they can never be closed during the
connection lifetime.

3 years agoMINOR: mux-quic: adjust timeout to accelerate closing
Amaury Denoyelle [Mon, 4 Apr 2022 14:15:06 +0000 (16:15 +0200)] 
MINOR: mux-quic: adjust timeout to accelerate closing

Improve timeout handling on the MUX. When releasing a stream, first
check if the connection can be considered as dead and should be freed
immediatly. This allows to liberate resources faster when possible.

If the connection is still active, ensure there is no attached
conn-stream before scheduling the timeout. To do this, add a nb_cs field
in the qcc structure.

3 years agoMINOR: mux-quic: factorize conn-stream attach
Amaury Denoyelle [Mon, 4 Apr 2022 14:13:44 +0000 (16:13 +0200)] 
MINOR: mux-quic: factorize conn-stream attach

Provide a new function qc_attach_cs. This must be used by the app layer
when a conn-stream can be instantiated. This will simplify future
development.

3 years agoBUG/MINOR: fix memleak on quic-conn streams cleaning
Amaury Denoyelle [Fri, 1 Apr 2022 14:41:21 +0000 (16:41 +0200)] 
BUG/MINOR: fix memleak on quic-conn streams cleaning

When freeing a quic-conn, the streams resources attached to it must be
cleared. This code is already implemented but the streams buffer was not
deallocated.

Fix this by using the function qc_stream_desc_free. This existing
function centralize all operations to properly free all streams
elements, attached both to the MUX and the quic-conn.

This fixes a memory leak which can happen for each released connection.

3 years agoCLEANUP: mux-quic: remove unused QC_CF_CC_RECV
Amaury Denoyelle [Wed, 6 Apr 2022 13:50:04 +0000 (15:50 +0200)] 
CLEANUP: mux-quic: remove unused QC_CF_CC_RECV

This flag was used to notify the MUX about a CONNECTION_CLOSE frame
reception. It is now unused on the MUX side and can be removed. A new
mechanism to detect quic-conn closing will be soon implemented.

3 years agoCLEANUP: quic: use static qualifer on quic_close
Amaury Denoyelle [Tue, 5 Apr 2022 15:34:18 +0000 (17:34 +0200)] 
CLEANUP: quic: use static qualifer on quic_close

quic_close can be used through xprt-ops and can thus be kept as a static
symbol.

3 years agoBUG/MEDIUM: quic: ensure quic-conn survives to the MUX
Amaury Denoyelle [Wed, 6 Apr 2022 15:22:12 +0000 (17:22 +0200)] 
BUG/MEDIUM: quic: ensure quic-conn survives to the MUX

Rationalize the lifetime of the quic-conn regarding with the MUX. The
quic-conn must not be freed if the MUX is still allocated.

This simplify the MUX code when accessing the quic-conn and removed
possible segfaults.

To implement this, if the quic-conn timer expired, the quic-conn is
released only if the MUX is not allocated. Else, the quic-conn is
flagged with QUIC_FL_CONN_EXP_TIMER. The MUX is then responsible
to call quic_close() which will free the flagged quic-conn.

3 years agoMINOR: quic: Add closing connection state
Frédéric Lécaille [Mon, 28 Mar 2022 10:13:09 +0000 (12:13 +0200)] 
MINOR: quic: Add closing connection state

New received packets after sending CONNECTION_CLOSE frame trigger a new
CONNECTION_CLOSE frame to be sent. Each time such a frame is sent we
increase the number of packet required to send another CONNECTION_CLOSE
frame.
Rearm only one time the idle timer when sending a CONNECTION_CLOSE frame.

3 years agoMINOR: quic: Add draining connection state.
Frédéric Lécaille [Fri, 25 Mar 2022 08:12:16 +0000 (09:12 +0100)] 
MINOR: quic: Add draining connection state.

As soon as we receive a CONNECTION_CLOSE frame, we must stop sending packets.
We add QUIC_FL_CONN_DRAINING connection flag to do so.

3 years agoBUG/MINOR: httpclient: end callback in applet release
William Lallemand [Wed, 6 Apr 2022 12:12:37 +0000 (14:12 +0200)] 
BUG/MINOR: httpclient: end callback in applet release

In case an error provokes the release of the applet, we will never call
the end callback of the httpclient.

In the case of a lua script, it would mean that the lua task will never
be waked up after a yield, letting the lua script stuck forever.

Fix the issue by moving the callback from the end of the iohandler to
the applet release function.

Must be backported in 2.5.

3 years agoMEDIUM: httpclient: enable l7-retry
William Lallemand [Thu, 17 Mar 2022 14:24:28 +0000 (15:24 +0100)] 
MEDIUM: httpclient: enable l7-retry

Enable the layer-7 retry in the httpclient. This way the client will
retry upon a connection error or a timeout.

3 years agoMINOR: httpclient: enable request buffering
William Lallemand [Fri, 18 Mar 2022 16:57:15 +0000 (17:57 +0100)] 
MINOR: httpclient: enable request buffering

The request buffering is required for doing l7 retry. The IO handler of
the httpclient need to be rework for that.

This patch change the IO handler so it copies partially the data instead
of swapping buffer. This is needed because the b_xfer won't never work
if the destination buffer is not empty, which is the case when
buffering.

3 years agoBUG/MINOR: ssl/cli: Remove empty lines from CLI output
Remi Tricot-Le Breton [Tue, 5 Apr 2022 14:44:21 +0000 (16:44 +0200)] 
BUG/MINOR: ssl/cli: Remove empty lines from CLI output

There were empty lines in the output of "show ssl ca-file <cafile>" and
"show ssl crl-file <crlfile>" commands when an empty line should only
mark the end of the output. This patch adds a space to those lines.

This patch should be backported to 2.5.

3 years agoBUG/MINOR: ssl: handle X509_get_default_cert_dir() returning NULL
William Lallemand [Tue, 5 Apr 2022 08:19:30 +0000 (10:19 +0200)] 
BUG/MINOR: ssl: handle X509_get_default_cert_dir() returning NULL

ssl_store_load_locations_file() is using X509_get_default_cert_dir()
when using '@system-ca' as a parameter.

This function could return a NULL if OpenSSL was built with a
X509_CERT_DIR set to NULL, this is uncommon but let's fix this.

No backport needed, 2.6 only.

Fix issue #1637.

3 years agoMINOR: sample: converter: Add add_item convertor
Nikola Sale [Sun, 3 Apr 2022 16:11:53 +0000 (18:11 +0200)] 
MINOR: sample: converter: Add add_item convertor

This new converter is similar to the concat converter and can be used to
build new variables made of a succession of other variables but the main
difference is that it does the checks if adding a delimiter makes sense as
wouldn't be the case if e.g the current input sample is empty. That
situation would require 2 separate rules using concat converter where the
first rule would have to check if the current sample string is empty before
adding a delimiter. This resolves GitHub Issue #1621.

3 years agoDOC: configuration: add the ca-file changes
William Lallemand [Fri, 1 Apr 2022 21:49:11 +0000 (23:49 +0200)] 
DOC: configuration: add the ca-file changes

Add the documentation about the directory support and @system-ca for the
"ca-file" directive.

3 years agoMINOR: ssl: ca-file @system-ca loads the system trusted CA
William Lallemand [Fri, 1 Apr 2022 21:39:37 +0000 (23:39 +0200)] 
MINOR: ssl: ca-file @system-ca loads the system trusted CA

The new parameter "@system-ca" to the ca-file directives loads the
trusted CA in the directory returned by X509_get_default_cert_dir().

3 years agoBUG/MINOR: ssl: continue upon error when opening a directory w/ ca-file
William Lallemand [Fri, 1 Apr 2022 21:36:05 +0000 (23:36 +0200)] 
BUG/MINOR: ssl: continue upon error when opening a directory w/ ca-file

Previous patch was accidentaly breaking upon an error when itarating
through a CA directory. This is not the expected behavior, the function
must start processing the other files after the warning.

3 years agoMEDIUM: ssl: allow loading of a directory with the ca-file directive
William Lallemand [Fri, 1 Apr 2022 18:12:03 +0000 (20:12 +0200)] 
MEDIUM: ssl: allow loading of a directory with the ca-file directive

This patch implements the ability to load a certificate directory with
the "ca-file" directive.

The X509_STORE_load_locations() API does not allow to cache a directory
in memory at startup, it only references the directory to allow a lookup
of the files when needed. But that is not compatible with the way
HAProxy works, without any access to the filesystem.

The current implementation loads every ".pem", ".crt", ".cer", and
".crl" available in the directory which is what is done when using
c_rehash and X509_STORE_load_locations(). Those files are cached in the
same X509_STORE referenced by the directory name. When looking at "show ssl
ca-file", everything will be shown in the same entry.

This will eventually allow to load more easily the CA of the system,
which could already be done with "ca-file /etc/ssl/certs" in the
configuration.

Loading failure intentionally emit a warning instead of an alert,
letting HAProxy starts when one of the files can't be loaded.

Known limitations:

- There is a bug in "show ssl ca-file", once the buffer is full, the
iohandler is not called again to output the next entries.

- The CLI API is kind of limited with this, since it does not allow to
  add or remove a entry in a particular ca-file. And with a lot of
  CAs you can't push them all in a buffer. It probably needs a "add ssl
  ca-file" like its done with the crt-list.

Fix issue #1476.

3 years agoOPTIM: hpack: read 32 bits at once when possible.
Willy Tarreau [Fri, 1 Apr 2022 15:16:44 +0000 (17:16 +0200)] 
OPTIM: hpack: read 32 bits at once when possible.

As suggested in the comment, it's possible to read 32 bits at once in
big-endian order, and now we have the functions to do this, so let's
do it. This reduces the code on the fast path by 31 bytes on x86, and
more importantly performs single-operation 32-bit reads instead of
playing with shifts and additions.

3 years agoCLEANUP: hpack: be careful about integer promotion from uint8_t
Willy Tarreau [Fri, 1 Apr 2022 15:12:08 +0000 (17:12 +0200)] 
CLEANUP: hpack: be careful about integer promotion from uint8_t

As reported in issue #1635, there's a subtle sign change when shifting
a uint8_t value to the left because integer promotion first turns any
smaller type to signed int *even if it was unsigned*. A warning was
reported about uint8_t shifted left 24 bits that couldn't fit in int
due to this.

It was verified that the emitted code didn't change, as expected, but
at least this allows to silence the code checkers. There's no need to
backport this.

3 years agoBUG/MINOR: quic: Missing TX packet deallocations
Frédéric Lécaille [Fri, 1 Apr 2022 10:15:24 +0000 (12:15 +0200)] 
BUG/MINOR: quic: Missing TX packet deallocations

Ensure all TX packets are deallocated. There may be remaining ones which
will never be acknowledged or deemed lost.

3 years agoBUG/MINOR: quic: Missing ACK range deallocations
Frédéric Lécaille [Fri, 1 Apr 2022 09:57:19 +0000 (11:57 +0200)] 
BUG/MINOR: quic: Missing ACK range deallocations

free_quic_arngs() was implemented but not used. Let's call it from
quic_conn_release().

3 years agoBUG/MINOR: quic: QUIC TLS secrets memory leak
Frédéric Lécaille [Fri, 1 Apr 2022 09:21:47 +0000 (11:21 +0200)] 
BUG/MINOR: quic: QUIC TLS secrets memory leak

We deallocate these secrets from quic_conn_release().

3 years agoBUG/MINOR: h3: Missing wait event struct field initialization
Frédéric Lécaille [Fri, 1 Apr 2022 07:04:57 +0000 (09:04 +0200)] 
BUG/MINOR: h3: Missing wait event struct field initialization

This one has been detected by valgrind:
==2179331== Conditional jump or move depends on uninitialised value(s)
==2179331==    at 0x1B6EDE: qcs_notify_recv (mux_quic.c:201)
==2179331==    by 0x1A17C5: qc_handle_uni_strm_frm (xprt_quic.c:2254)
==2179331==    by 0x1A1982: qc_handle_strm_frm (xprt_quic.c:2286)
==2179331==    by 0x1A2CDB: qc_parse_pkt_frms (xprt_quic.c:2550)
==2179331==    by 0x1A6068: qc_treat_rx_pkts (xprt_quic.c:3463)
==2179331==    by 0x1A6C3D: quic_conn_app_io_cb (xprt_quic.c:3589)
==2179331==    by 0x3AA566: run_tasks_from_lists (task.c:580)
==2179331==    by 0x3AB197: process_runnable_tasks (task.c:883)
==2179331==    by 0x357E56: run_poll_loop (haproxy.c:2750)
==2179331==    by 0x358366: run_thread_poll_loop (haproxy.c:2921)
==2179331==    by 0x3598D2: main (haproxy.c:3538)
==2179331==

3 years agoMINOR: quic: Add traces about list of frames
Frédéric Lécaille [Thu, 31 Mar 2022 18:26:18 +0000 (20:26 +0200)] 
MINOR: quic: Add traces about list of frames

This should be useful to have an idea of the list of frames which could be built
towards the list of available frames when building packets.
Same thing about the frames which could not be built because of a lack of room
in the TX buffer.

3 years agoMINOR: quic: Useless call to SSL_CTX_set_default_verify_paths()
Frédéric Lécaille [Thu, 31 Mar 2022 14:37:01 +0000 (16:37 +0200)] 
MINOR: quic: Useless call to SSL_CTX_set_default_verify_paths()

This call to SSL_CTX_set_default_verify_paths() is useless for haproxy.

3 years agoBUG/MINOR: quic: Too much prepared retransmissions due to anti-amplification
Frédéric Lécaille [Thu, 31 Mar 2022 06:42:06 +0000 (08:42 +0200)] 
BUG/MINOR: quic: Too much prepared retransmissions due to anti-amplification

We must not re-enqueue frames if we can detect in advance they will not be
transmitted due to the anti-amplification limit.

3 years agoBUG/MINOR: quic: Non duplicated frames upon fast retransmission
Frédéric Lécaille [Wed, 30 Mar 2022 12:58:55 +0000 (14:58 +0200)] 
BUG/MINOR: quic: Non duplicated frames upon fast retransmission

We must duplicate the frames to be sent again from packets which are not deemed
lost.

3 years agoBUG/MINOR: quic: Do not probe from an already probing packet number space
Frédéric Lécaille [Wed, 30 Mar 2022 12:44:49 +0000 (14:44 +0200)] 
BUG/MINOR: quic: Do not probe from an already probing packet number space

During a handshake, after having prepared a probe upon a PTO expiration from
process_timer(), we wake up the I/O handler to make it send probing packets.
This handler first treat incoming packets  which trigger a fast retransmission
leading to send too much probing (duplicated) packets. In this cas we cancel
the fast retranmission.

3 years agoMINOR: quic: Do not display any timer value from process_timer()
Frédéric Lécaille [Wed, 30 Mar 2022 12:36:40 +0000 (14:36 +0200)] 
MINOR: quic: Do not display any timer value from process_timer()

This is confusing to display the connection timer from this function as it is not
supposed to update it. Only qc_set_timer() should do that.

3 years agoBUG/MINOR: quic: Discard Initial packet number space only one time
Frédéric Lécaille [Tue, 29 Mar 2022 17:09:46 +0000 (19:09 +0200)] 
BUG/MINOR: quic: Discard Initial packet number space only one time

When discarding a packet number space, we at least reset the PTO backoff counter.
Doing this several times have an impact on the PTO duration calculation.
We must not discard a packet number space several times (this is already the case
for the handshake packet number space).

3 years agoBUG/MINOR: quic: Missing probing packets when coalescing
Frédéric Lécaille [Tue, 29 Mar 2022 15:41:57 +0000 (17:41 +0200)] 
BUG/MINOR: quic: Missing probing packets when coalescing

Before having a look at the next encryption level to build packets if there is
no more ack-eliciting frames to send we must check we have not to probe from
the current encryption level anymore. If not, we only send one datagram instead
of sending two datagrams giving less chance to recover from packet loss.

3 years agoMEDIUM: quic: Send ACK frames asap
Frédéric Lécaille [Tue, 29 Mar 2022 09:42:03 +0000 (11:42 +0200)] 
MEDIUM: quic: Send ACK frames asap

Due to a erroneous interpretation of the RFC 9000 (quic-transport), ACKs frames
were always sent only after having received two ack-eliciting packets.
This could trigger useless retransmissions for tail packets on the peer side.
For now on, we send as soon as possible ACK frames as soon as we have ACK to send,
in the same packets as the ack-eliciting frame packets, and we also send ACK
frames after having received 2 ack-eliciting packets since the last time we sent
an ACK frame with other ack-eliciting frames.

3 years agoCLEANUP: quic: Remove all atomic operations on packet number spaces
Frédéric Lécaille [Mon, 28 Mar 2022 15:38:27 +0000 (17:38 +0200)] 
CLEANUP: quic: Remove all atomic operations on packet number spaces

As such variables are handled by the QUIC connection I/O handler which runs
always on the thread, there is no need to continue to use such atomic operations

3 years agoCLEANUP: quic: Remove all atomic operations on quic_conn struct
Frédéric Lécaille [Mon, 28 Mar 2022 15:10:31 +0000 (17:10 +0200)] 
CLEANUP: quic: Remove all atomic operations on quic_conn struct

As the QUIC connections are always handled by the same thread there is no need
anymore to continue to use atomic operations on such variables.

3 years agoBUG/MEDIUM: quic: Possible crash in ha_quic_set_encryption_secrets()
Frédéric Lécaille [Sat, 26 Mar 2022 11:22:41 +0000 (12:22 +0100)] 
BUG/MEDIUM: quic: Possible crash in ha_quic_set_encryption_secrets()

This bug has come with this commit:
   1fc5e16c4 MINOR: quic: More accurate immediately close
As mentionned in this commit we do not want to derive anymore secret when in closing
state. But the flag which denote secrets were derived was set. Add a label at
the correct flag to skip the secrets derivation without setting this flag.

3 years agoCI: github actions: update OpenSSL to 3.0.2
Ilya Shipitsin [Sun, 27 Mar 2022 05:51:51 +0000 (10:51 +0500)] 
CI: github actions: update OpenSSL to 3.0.2

3 years agoDOC: remove double blanks in configuration.txt
Aleksandar Lazic [Tue, 29 Mar 2022 22:11:40 +0000 (00:11 +0200)] 
DOC: remove double blanks in configuration.txt

Double blanks in keywords are not good for the html documentation parser.
This commit fixes the double blanks for tcp-request content use-service.

3 years agoBUG/MAJOR: mux_pt: always report the connection error to the conn_stream
Willy Tarreau [Thu, 31 Mar 2022 14:47:46 +0000 (16:47 +0200)] 
BUG/MAJOR: mux_pt: always report the connection error to the conn_stream

Over time we've tried hard to abstract connection errors from the upper
layers so that they're reported per stream and not per connection. As
early as 1.8-rc1, commit 4ff3b8964 ("MINOR: connection: make conn_stream
users also check for per-stream error flag") did precisely this, but
strangely only for rx, not for tx (probably that by then send errors
were not imagined to be reported that way).

And this lack of Tx error check was just revealed in 2.6 by recent commit
d1480cc8a ("BUG/MEDIUM: stream-int: do not rely on the connection error
once established") that causes wakeup loops between si_cs_send() failing
to send via mux_pt_snd_buf() and subscribing against si_cs_io_cb() in
loops because the function now rightfully only checks for CS_FL_ERROR
and not CO_FL_ERROR.

As found by Amaury, this causes aborted "show events -w" to cause
haproxy to loop at 100% CPU.

This fix theoretically needs to be backported to all versions, though
it will be necessary and sufficient to backport it wherever 4ff3b8964
gets backported.

3 years agoDOC: management: add missing dot in 9.4.1
William Lallemand [Thu, 31 Mar 2022 13:26:51 +0000 (15:26 +0200)] 
DOC: management: add missing dot in 9.4.1

The 9.4.1 chapter is missing the dot at the end of the chapter numbers.
Which broke the haproxy-dconv html generation.

No backport needed, 2.6 only.

3 years agoBUG/MINOR: cli/stream: fix "shutdown session" to iterate over all threads
Willy Tarreau [Thu, 31 Mar 2022 12:49:45 +0000 (14:49 +0200)] 
BUG/MINOR: cli/stream: fix "shutdown session" to iterate over all threads

The list of streams was modified in 2.4 to become per-thread with commit
a698eb673 ("MINOR: streams: use one list per stream instead of a global
one"). However the change applied to cli_parse_shutdown_session() is
wrong, as it uses the nullity of the stream pointer to continue on next
threads, but this one is not null once the list_for_each_entry() loop
is finished, it points to the list's head again, so the loop doesn't
check other threads, and no message is printed either to say that the
stream was not found.

Instead we should check if the stream is equal to the requested pointer
since this is the condition to break out of the loop.

Thus must be backported to 2.4. Thanks to Maciej Zdeb for reporting this.

3 years agoMEDIUM: mux-quic: remove qcs tree node
Amaury Denoyelle [Tue, 29 Mar 2022 13:18:44 +0000 (15:18 +0200)] 
MEDIUM: mux-quic: remove qcs tree node

The new qc_stream_desc type has a tree node for storage. Thus, we can
remove the node in the qcs structure.

When initializing a new stream, it is stored into the qcc streams_by_id
tree. When the MUX releases it, it will freed as soon as its buffer is
emptied. Before this, the quic-conn is responsible to store it inside
its own streams_by_id tree.

3 years agoMEDIUM: quic: move transport fields from qcs to qc_conn_stream
Amaury Denoyelle [Tue, 29 Mar 2022 13:15:54 +0000 (15:15 +0200)] 
MEDIUM: quic: move transport fields from qcs to qc_conn_stream

Move the xprt-buf and ack related fields from qcs to the qc_stream_desc
structure. In exchange, qcs has a pointer to the low-level stream. For
each new qcs, a qc_stream_desc is automatically allocated.

This simplify the transport layer by removing qcs/mux manipulation
during ACK frame parsing. An additional check is done to not notify the
MUX on sending if the stream is already released : this case may now
happen on retransmission.

To complete this change, the quic_stream frame now references the
quic_stream instance instead of a qcs.

3 years agoMINOR: quic: implement stream descriptor for transport layer
Amaury Denoyelle [Tue, 29 Mar 2022 12:49:35 +0000 (14:49 +0200)] 
MINOR: quic: implement stream descriptor for transport layer

Currently, the mux qcs streams manage the Tx buffering, even after
sending it to the transport layer. Buffers are emptied when
acknowledgement are treated by the transport layer. This complicates the
MUX liberation and we may loose some data after the MUX free.

Change this paradigm by moving the buffering on the transport layer. For
this goal, a new type is implemented as low-level stream at the
transport layer, as a counterpart of qcs mux instances. This structure
is called qc_stream_desc. This will allow to free the qcs/qcc instances
without having to wait for acknowledge reception.

For the moment, the quic-conn is responsible to store the qc_stream_desc
in a new tree named streams_by_id. This will sligthly change in the next
commits to remove the qcs node which has a similar purpose :
qc_stream_desc instances will be shared between the qcc MUX and the
quic-conn.

This patch only introduces the new type definition and the function to
manipulate it. The following commit will bring the rearchitecture in the
qcs structure.

3 years agoCLEANUP: quic: complete comment on qcs_try_to_consume
Amaury Denoyelle [Tue, 29 Mar 2022 12:50:25 +0000 (14:50 +0200)] 
CLEANUP: quic: complete comment on qcs_try_to_consume

Specify the return value usage.

3 years agoBUG/MINOR: mux-quic: ensure to free all qcs on MUX release
Amaury Denoyelle [Wed, 30 Mar 2022 09:51:56 +0000 (11:51 +0200)] 
BUG/MINOR: mux-quic: ensure to free all qcs on MUX release

Remove qcs instances left during qcc MUX release. This can happen when
the MUX is closed before the completion of all the transfers, such as on
a timeout or process termination.

This may free some memory leaks on the connection.

3 years agoBUG/MINOR: h3: release resources on close
Amaury Denoyelle [Tue, 29 Mar 2022 12:46:55 +0000 (14:46 +0200)] 
BUG/MINOR: h3: release resources on close

Implement the release app-ops ops for H3 layer. This is used to clean up
uni-directional streams and the h3 context.

This prevents a memory leak on H3 resources for each connection.

3 years agoMINOR: mux-quic: define release app-ops
Amaury Denoyelle [Tue, 29 Mar 2022 12:46:38 +0000 (14:46 +0200)] 
MINOR: mux-quic: define release app-ops

Define a new callback release inside qcc_app_ops. It is called when the
qcc MUX is freed via qc_release. This will allows to implement cleaning
on the app layer.

3 years agoMINOR: mux-quic: reorganize qcs free
Amaury Denoyelle [Tue, 29 Mar 2022 16:36:59 +0000 (18:36 +0200)] 
MINOR: mux-quic: reorganize qcs free

Regroup some cleaning operations inside a new function qcs_free. This
can be used for all streams, both through qcs_destroy and with
uni-directional streams.

3 years agoMINOR: mux-quic: return qcs instance from qcc_get_qcs
Amaury Denoyelle [Tue, 29 Mar 2022 12:57:19 +0000 (14:57 +0200)] 
MINOR: mux-quic: return qcs instance from qcc_get_qcs

Refactoring on qcc_get_qcs : return the qcs instance instead of the tree
node. This is useful to hide some eb64_entry macros for better
readability.

3 years agoBUG/MEDIUM: quic: do not use qcs from quic_stream on ACK parsing
Amaury Denoyelle [Tue, 29 Mar 2022 09:51:17 +0000 (11:51 +0200)] 
BUG/MEDIUM: quic: do not use qcs from quic_stream on ACK parsing

The quic_stream frame stores the qcs instance. On ACK parsing, qcs is
accessed to clear the stream buffer. This can cause a segfault if the
MUX or the qcs is already released.

Consider the following scenario :

1. a STREAM frame is generated by the MUX
   transport layer emits the frame with PKN=1
   upper layer has finished the transfer so related qcs is detached

2. transport layer reemits the frame with PKN=2 because ACK was not
   received

3. ACK for PKN=1 is received, stream buffer is cleared
   at this stage, qcs may be freed by the MUX as it is detached

4. ACK for PKN=2 is received
   qcs for STREAM frame is dereferenced which will lead to a crash

To prevent this, qcs is never accessed from the quic_stream during ACK
parsing. Instead, a lookup is done on the MUX streams tree. If the MUX
is already released, no lookup is done. These checks prevents a possible
segfault.

This change may have an impact on the perf as now we are forced to use a
tree lookup operation. If this is the case, an alternative solution may
be to implement a refcount on qcs instances.

3 years agoDOC: lua: CertCache class documentation
William Lallemand [Wed, 30 Mar 2022 14:02:43 +0000 (16:02 +0200)] 
DOC: lua: CertCache class documentation

Document the CertCache API which is used to update a certificate file in
memory using lua.

3 years agoBUILD: ssl/lua: CacheCert needs OpenSSL
William Lallemand [Wed, 30 Mar 2022 13:05:42 +0000 (15:05 +0200)] 
BUILD: ssl/lua: CacheCert needs OpenSSL

Return an lua error when trying to use CacheCert.set() and OpenSSL was
not used to build HAProxy.

3 years agoMINOR: ssl/lua: CertCache.set() allows to update an SSL certificate file
William Lallemand [Wed, 30 Mar 2022 10:03:12 +0000 (12:03 +0200)] 
MINOR: ssl/lua: CertCache.set() allows to update an SSL certificate file

The CertCache.set() function allows to update an SSL certificate file
stored in the memory of the HAProxy process. This function does the same
as "set ssl cert" + "commit ssl cert" over the CLI.

This could be used to update the crt and key, as well as the OCSP, the
SCTL, and the OSCP issuer.

The implementation does yield every 10 ckch instances, the same way the
"commit ssl cert" do.

3 years agoMINOR: ssl: add "crt" in the cert_exts array
William Lallemand [Wed, 30 Mar 2022 10:01:32 +0000 (12:01 +0200)] 
MINOR: ssl: add "crt" in the cert_exts array

The cert_exts array does handle "crt" the default way, however
you might stil want to look for these extensions in the array.

3 years agoMINOR: ssl: export ckch_inst_rebuild()
William Lallemand [Wed, 30 Mar 2022 09:26:15 +0000 (11:26 +0200)] 
MINOR: ssl: export ckch_inst_rebuild()

ckch_inst_rebuild() will be needed to regenerate the ckch instances from
the lua code, we need to export it.

3 years agoMINOR: ssl: simplify the certificate extensions array
William Lallemand [Tue, 29 Mar 2022 08:44:23 +0000 (10:44 +0200)] 
MINOR: ssl: simplify the certificate extensions array

Simplify the "cert_exts" array which is used for the selection of the
parsing function depending on the extension.

It now uses a pointer to an array element instead of an index, which is
simplier for the declaration of the array.

This way also allows to have multiple extension using the same type.

3 years agoMINOR: ssl: move the cert_exts and the CERT_TYPE enum
William Lallemand [Thu, 24 Mar 2022 16:48:40 +0000 (17:48 +0100)] 
MINOR: ssl: move the cert_exts and the CERT_TYPE enum

Move the cert_exts declaration and the CERT_TYPE enum in the .h in order
to reuse them in another file.

3 years agoMINOR: ssl: split the cert commit io handler
William Lallemand [Tue, 29 Mar 2022 12:29:31 +0000 (14:29 +0200)] 
MINOR: ssl: split the cert commit io handler

Extract the code that replace the ckch_store and its dependencies into
the ckch_store_replace() function.

This function must be used under the global ckch lock.
It frees everything related to the old ckch_store.

3 years agoMEDIUM: httpclient/lua: be stricter with httpclient parameters
William Lallemand [Thu, 3 Mar 2022 14:33:12 +0000 (15:33 +0100)] 
MEDIUM: httpclient/lua: be stricter with httpclient parameters

Checks the argument passed to the httpclient send functions so we don't
add a mispelled argument.

3 years agoMINOR: services: alphabetically sort service names
Willy Tarreau [Wed, 30 Mar 2022 10:12:44 +0000 (12:12 +0200)] 
MINOR: services: alphabetically sort service names

Note that we cannot reuse dump_act_rules() because the output format
may be adjusted depending on the call place (this is also used from
haproxy -vv). The principle is the same however.