]> git.ipfire.org Git - thirdparty/haproxy.git/log
thirdparty/haproxy.git
3 weeks agoMINOR: h3: prepare support for response parsing
Amaury Denoyelle [Wed, 28 May 2025 15:07:07 +0000 (17:07 +0200)] 
MINOR: h3: prepare support for response parsing

Refactor HTTP/3 request headers transcoding to HTX done in
h3_headers_to_htx(). Some operations are extracted into dedicated
functions, to check pseudo-headers and headers conformity, and also trim
the value of headers before encoding it in HTX.

The objective will be to simplify implementation of HTTP/3 response
transcoding by reusing these functions.

Also, h3_headers_to_htx() has been renamed to h3_req_headers_to_htx(),
to highlight that it is reserved to frontend usage.

3 weeks agoMINOR: h3: adjust auth request encoding or fallback to host
Amaury Denoyelle [Fri, 30 May 2025 16:00:48 +0000 (18:00 +0200)] 
MINOR: h3: adjust auth request encoding or fallback to host

Implement proper encoding of HTTP/3 authority pseudo-header during
request transcoding on the backend side. A pseudo-header :authority is
encoded if a value can be extracted from HTX start-line. A special check
is also implemented to ensure that a host header is not encoded if
:authority already is.

A new function qpack_encode_auth() is defined to implement QPACK
encoding of :authority header using literal field line with name ref.

3 weeks agoMINOR: h3: adjust path request encoding
Amaury Denoyelle [Fri, 30 May 2025 14:25:15 +0000 (16:25 +0200)] 
MINOR: h3: adjust path request encoding

Previously, HTTP/3 backend request :path was hardcoded to value '/'.
Change this so that we can now encode any path as requested by the
client. Path is extracted from the HTX URI. Also, qpack_encode_path() is
extended to support literal field line with name ref.

3 weeks agoMINOR: h3: complete HTTP/3 request scheme encoding
Amaury Denoyelle [Fri, 30 May 2025 09:48:00 +0000 (11:48 +0200)] 
MINOR: h3: complete HTTP/3 request scheme encoding

Previously, scheme was always set to https when transcoding an HTX
start-line into a HTTP/3 request. Change this so this conversion is now
fully compliant.

If no scheme is specified by the client, which is what happens most of
the time with HTTP/1, https is set for the HTTP/3 request. Else, reuse
the scheme requested by the client.

If either https or http is set, qpack_encode_scheme will encode it using
entry from QPACK static table. Else, a full literal field line with name
ref is used instead as the scheme value is specified as-is.

3 weeks agoMINOR: h3: complete HTTP/3 request method encoding
Amaury Denoyelle [Fri, 30 May 2025 13:59:04 +0000 (15:59 +0200)] 
MINOR: h3: complete HTTP/3 request method encoding

On the backend side, HTX start-line is converted into a HTTP/3 request
message. Previously, GET method was hardcoded. Implement proper method
conversion, by extracting it from the HTX start-line.

qpack_encode_method() has also been extended, so that it is able to
encode any method, either using a static table entry, or with a literal
field line with name ref representation.

3 weeks agoMINOR: h3: encode request headers
Amaury Denoyelle [Mon, 16 Jun 2025 13:38:26 +0000 (15:38 +0200)] 
MINOR: h3: encode request headers

Implement encoding of HTTP/3 request headers during HTX->H3 conversion
on the backend side. This simply relies on h3_encode_header().

Special check is implemented to ensure that connection-specific headers
are ignored. An HTTP/3 endpoint must never generate them, or the peer
will consider the message as malformed.

3 weeks agoMINOR: h3: support basic HTX start-line conversion into HTTP/3 request
Amaury Denoyelle [Wed, 28 May 2025 09:24:43 +0000 (11:24 +0200)] 
MINOR: h3: support basic HTX start-line conversion into HTTP/3 request

This commit is the first one of a serie which aim is to implement
transcoding of a HTX request into HTTP/3, which is necessary for QUIC
backend support.

Transcoding is implementing via a new function h3_req_headers_send()
when a HTX start-line is parsed. For now, most of the request fields are
hardcoded, using a GET method. This will be adjusted in the next
following patches.

3 weeks agoBUG/MINOR: mux-quic: check sc_attach_mux return value
Amaury Denoyelle [Mon, 16 Jun 2025 08:46:05 +0000 (10:46 +0200)] 
BUG/MINOR: mux-quic: check sc_attach_mux return value

On backend side, QUIC MUX needs to initialize the first local stream
during MUX init operation. This is necessary so that the first transfer
can then be performed.

sc_attach_mux() is used to attach the created QCS instance to its stream
data layer. However, return value was not checked, which may cause
issues on allocation error. This patch fixes it by returning an error on
MUX init operation and freeing the QCS instance in case of
sc_attach_mux() error.

This fixes coverity report from github issue #3007.

No need to backport.

3 weeks agoBUG/MEDIUM: check: Set SOCKERR by default when a connection error is reported
Christopher Faulet [Mon, 16 Jun 2025 14:33:04 +0000 (16:33 +0200)] 
BUG/MEDIUM: check: Set SOCKERR by default when a connection error is reported

When a connection error is reported, we try to collect as much information
as possible on the connection status and the server status is adjusted
accordingly. However, the function does nothing if there is no connection
error and if the healthcheck is not expired yet. It is a problem when an
internal error occurred. It may happen at many places and it is hard to be
sure an error is reported on the connection. And in fact, it is already a
problem when the multiplexer allocation fails. In that case, the healthcheck
is not interrupted as it should be. Concretely, it could only happen when a
connection is established.

It is hard to predict the effects of this bug. It may be unimportant. But it
could probably lead to a crash. To avoid any issue, a SOCKERR status is now
set by default when a connection error is reported. There is no reason to
report a connection error for nothing. So a healthcheck failure must be
reported. There is no "internal error" status. So a socket error is
reported.

This patch must be backport to all stable versions.

3 weeks agoMINOR: cli: handle EOS/ERROR first
Christopher Faulet [Mon, 16 Jun 2025 14:29:07 +0000 (16:29 +0200)] 
MINOR: cli: handle EOS/ERROR first

It is not especially a bug fixed. But APPCTX_FL_EOS and APPCTX_FL_ERROR
flags must be handled first. These flags are set by the applet itself and
should mark the end of all processing. So there is not reason to get the
output buffer in first place.

This patch could be backported as far as 3.0.

3 weeks agoBUG/MEDIUM: cli: Don't consume data if outbuf is full or not available
Christopher Faulet [Mon, 16 Jun 2025 13:48:04 +0000 (15:48 +0200)] 
BUG/MEDIUM: cli: Don't consume data if outbuf is full or not available

The output buffer must be available to process a command, at least to be
able to emit error messages. When this buffer is full or cannot be
allocated, we must wait. In that case, we must take care to notify the SE
will not consume input data. It is important to avoid wakeup in loop,
especially when the client aborts.

When the output buffer is available again and no longer full, and the CLI
applet is waiting for a command line, it must notify it will consume input
data.

This patch must be backported as far as 3.0.

3 weeks agoBUG/MINOR: quic: fix ODCID initialization on frontend side
Amaury Denoyelle [Mon, 16 Jun 2025 08:02:47 +0000 (10:02 +0200)] 
BUG/MINOR: quic: fix ODCID initialization on frontend side

QUIC support on the backend side has been implemented recently. This has
lead to some adjustment on qc_new_conn() to handle both FE and BE sides,
with some of these changes performed by the following commit.

  29fb1aee57288a8b16ed91771ae65c2bfa400128
  MINOR: quic-be: QUIC connection allocation adaptation (qc_new_conn())

An issue was introduced during some code adjustement. Initialization of
ODCID was incorrectly performed, which caused haproxy to emit invalid
transport parameters. Most of the clients detected this and immediatly
closed the connection.

Fix this by adjusting qc_lstnr_params_init() invokation : replace
<qc.dcid>, which in fact points to the received SCID, by <qc.odcid>
whose purpose is dedicated to original DCID storage.

This fixes github issue #3006. This issue also caused the majority of
tests in the interop to fail.

No backport needed.

3 weeks agoBUG/MINOR: quic: Fix OSSL_FUNC_SSL_QUIC_TLS_got_transport_params_fn callback (OpenSSL3.5)
Frederic Lecaille [Thu, 12 Jun 2025 15:37:49 +0000 (17:37 +0200)] 
BUG/MINOR: quic: Fix OSSL_FUNC_SSL_QUIC_TLS_got_transport_params_fn callback (OpenSSL3.5)

This patch is OpenSSL3.5 QUIC API specific. It fixes
OSSL_FUNC_SSL_QUIC_TLS_got_transport_params_fn() callback (see man(3) SSL_set_quic_tls_cb).

The role of this callback is to store the transport parameters received by the peer.
At this time it is never used by QUIC listeners because there is another callback
which is used to store the transport parameters. This latter callback is not specific
to OpenSSL 3.5 QUIC API. As far as I know, the TLS stack call only one time
one of the callbacks which have been set to receive and store the transport parameters.

That said, OSSL_FUNC_SSL_QUIC_TLS_got_transport_params_fn() is called for QUIC
backends to store the server transport parameters.

qc_ssl_set_quic_transport_params() is useless is this callback. It is dedicated
to store the local tranport parameters (which are sent to the peer). Furthermore
<server> second parameter of quic_transport_params_store() must be 0 for a listener
(or QUIC server) whichs call it, denoting it does not receive the transport parameters
of a QUIC server. It must be 1 for a QUIC backend (a QUIC client which receives
the transport parameter of a QUIC server).

Must be backported to 3.2.

3 weeks agoMINOR: hq-interop: handle HTX response forward if not enough space
Amaury Denoyelle [Fri, 13 Jun 2025 15:41:13 +0000 (17:41 +0200)] 
MINOR: hq-interop: handle HTX response forward if not enough space

On backend side, HTTP/0.9 response body is copied into stream data HTX
buffer. Properly handle the case where the HTX out buffer space is too
small. Only copy a partial copy of the HTTP response. Transcoding will
be restarted when new room is available.

3 weeks agoBUG/MINOR: quic: don't restrict reception on backend privileged ports
Amaury Denoyelle [Fri, 13 Jun 2025 08:19:16 +0000 (10:19 +0200)] 
BUG/MINOR: quic: don't restrict reception on backend privileged ports

When QUIC is used on the frontend side, communication is restricted with
clients using privileged port. This is a simple protection against
DNS/NTP spoofing.

This feature should not be activated on the backend side, as in this
case it is quite frequent to exchange with server running on privileged
ports. As such, a new parameter is added to quic_recv() so that it is
only active on the frontend side.

Without this patch, it is impossible to communicate with QUIC servers
running on privileged ports, as incoming datagrams would be silently
dropped.

No need to backport.

3 weeks agoBUG/MINOR: http-ana: Properly handle keep-query redirect option if no QS
Christopher Faulet [Fri, 13 Jun 2025 09:19:50 +0000 (11:19 +0200)] 
BUG/MINOR: http-ana: Properly handle keep-query redirect option if no QS

The keep-query redirect option must do nothing is there is no query-string.
However, there is a bug. When there is no QS, an error is returned, leading
to return a 500-internal-error to the client.

To fix the bug, instead of returning 0 when there is no QS, we just skip the
QS processing.

This patch should fix the issue #3005. It must be backported as far as 3.1.

3 weeks agoBUG/MINOR: quic: work around NEW_TOKEN parsing error on backend side
Amaury Denoyelle [Thu, 12 Jun 2025 15:39:31 +0000 (17:39 +0200)] 
BUG/MINOR: quic: work around NEW_TOKEN parsing error on backend side

NEW_TOKEN frame is never emitted by a client, hence parsing was not
tested on frontend side.

On backend side, an issue can occur, as expected token length is static,
based on the token length used internally by haproxy. This is not
sufficient for most server implementation which uses larger token. This
causes a parsing error, which may cause skipping of following frames in
the same packet. This issue was detected using ngtcp2 as server.

As for now tokens are unused by haproxy, simply discard test on token
length during NEW_TOKEN frame parsing. The token itself is merely
skipped without being stored. This is sufficient for now to continue on
experimenting with QUIC backend implementation.

This does not need to be backported.

3 weeks agoMINOR: server: reject QUIC servers without explicit SSL
Amaury Denoyelle [Thu, 12 Jun 2025 14:16:43 +0000 (16:16 +0200)] 
MINOR: server: reject QUIC servers without explicit SSL

Report an error during server configuration if QUIC is used by SSL is
not activiated via 'ssl' keyword. This is done in _srv_parse_finalize(),
which is both used by static and dynamic servers.

Note that contrary to listeners, an error is reported instead of a
warning, and SSL is not automatically activated if missing. This is
mainly due to the complex server configuration : _srv_parse_finalize()
is ideal to affect every servers, including dynamic entries. However, it
is executed after server SSL context allocation performed via
<prepare_srv> XPRT operation. A proper fix would be to move SSL ctx
alloc in _srv_parse_finalize(), but this may have unknown impact. Thus,
for now a simpler solution has been chosen.

3 weeks agoBUG/MINOR: quic: prevent crash on startup with -dt
Amaury Denoyelle [Thu, 12 Jun 2025 13:15:56 +0000 (15:15 +0200)] 
BUG/MINOR: quic: prevent crash on startup with -dt

QUIC traces in ssl_quic_srv_new_ssl_ctx() are problematic as this
function is called early during startup. If activating traces via -dt
command-line argument, a crash occurs due to stderr sink not yet
available.

Thus, traces from ssl_quic_srv_new_ssl_ctx() are simply removed.

No backport needed.

3 weeks agoMINOR: quic-be: Avoid SSL context unreachable code without USE_QUIC_OPENSSL_COMPAT
Frederic Lecaille [Thu, 12 Jun 2025 09:17:18 +0000 (11:17 +0200)] 
MINOR: quic-be: Avoid SSL context unreachable code without USE_QUIC_OPENSSL_COMPAT

This commit added a "err" C label reachable only with USE_QUIC_OPENSSL_COMPAT:

   MINOR: quic-be: Missing callbacks initializations (USE_QUIC_OPENSSL_COMPAT)

leading coverity to warn this:

*** CID 1611481:         Control flow issues  (UNREACHABLE)
/src/quic_ssl.c: 802             in ssl_quic_srv_new_ssl_ctx()
796      goto err;
797     #endif
798
799      leave:
800      TRACE_LEAVE(QUIC_EV_CONN_NEW);
801      return ctx;
>>>     CID 1611481:         Control flow issues  (UNREACHABLE)
>>>     This code cannot be reached: "err:
SSL_CTX_free(ctx);".
802      err:
803      SSL_CTX_free(ctx);
804      ctx = NULL;
805      TRACE_DEVEL("leaving on error", QUIC_EV_CONN_NEW);
806      goto leave;
807     }

The less intrusive (without #ifdef) way to fix this it to add a "goto err"
statement from the code part which is reachable without USE_QUIC_OPENSSL_COMPAT.

Thank you to @chipitsine for having reported this issue in GH #3003.

3 weeks agoBUG/MINOR: quic-be: CID double free upon qc_new_conn() failures
Frederic Lecaille [Thu, 12 Jun 2025 08:59:35 +0000 (10:59 +0200)] 
BUG/MINOR: quic-be: CID double free upon qc_new_conn() failures

This issue may occur when qc_new_conn() fails after having allocated
and attached <conn_cid> to its tree. This is the case when compiling
haproxy against WolfSSL for an unknown reason at this time. In this
case the <conn_cid> is freed by pool_head_quic_connection_id(), then
freed again by quic_conn_release().

This bug arrived with this commit:

    MINOR: quic-be: QUIC connection allocation adaptation (qc_new_conn())

So, the aim of this patch is to free <conn_cid> only for QUIC backends
and if it is not attached to its tree. This is the case when <conn_id>
local variable passed with NULL value to qc_new_conn() is then intialized
to the same <conn_cid> value.

3 weeks agoCLEANUP: quic-be: Add comments about qc_new_conn() usage
Frederic Lecaille [Thu, 12 Jun 2025 08:50:52 +0000 (10:50 +0200)] 
CLEANUP: quic-be: Add comments about qc_new_conn() usage

This patch should have come with this last commit for the last qc_new_conn()
modifications for QUIC backends:

     MINOR: quic-be: get rid of ->li quic_conn member

qc_new_conn() must be passed NULL pointers for several variables as mentioned
by the comment. Some of these local variables are used to avoid too much
code modifications.

3 weeks agoMINOR: hq-interop: encode request from HTX for backend side support
Amaury Denoyelle [Wed, 11 Jun 2025 09:45:40 +0000 (11:45 +0200)] 
MINOR: hq-interop: encode request from HTX for backend side support

Implement transcoding of a HTX request into HTTP/0.9. This protocol is a
simplified version of HTTP. Request only supports GET method without any
header. As such, only a request line is written during snd_buf
operation.

3 weeks agoMINOR: hq-interop: decode response into HTX for backend side support
Amaury Denoyelle [Fri, 6 Jun 2025 14:23:22 +0000 (16:23 +0200)] 
MINOR: hq-interop: decode response into HTX for backend side support

Implement transcoding of a HTTP/0.9 response into a HTX message.

HTTP/0.9 is a really simple substract of HTTP spec. The response does
not have any status line and is contains only the payload body. Response
is finished when the underlying connection/stream is closed.

A status line is generated to be compliant with HTX. This is performed
on the first invokation of rcv_buf for the current stream. Status code
is set to 200. Payload body if present is then copied using
htx_add_data().

3 weeks agoMINOR: quic: wakeup backend MUX on handshake completed
Amaury Denoyelle [Wed, 28 May 2025 09:26:08 +0000 (11:26 +0200)] 
MINOR: quic: wakeup backend MUX on handshake completed

This commit is the second and final step to initiate QUIC MUX on the
backend side. On handshake completion, MUX is woken up just after its
creation. This step is necessary to notify the stream layer, via the QCS
instance pre-initialized on MUX init, so that the transfer can be
resumed.

This mode of operation is similar to TCP stack when TLS+ALPN are used,
which forces MUX initialization to be delayed after handshake
completion.

3 weeks agoMINOR: mux-quic: instantiate first stream on backend side
Amaury Denoyelle [Wed, 11 Jun 2025 13:38:59 +0000 (15:38 +0200)] 
MINOR: mux-quic: instantiate first stream on backend side

Adjust qmux_init() to handle frontend and backend sides differently.
Most notably, on backend side, the first bidirectional stream is created
preemptively. This step is necessary as MUX layer will be woken up just
after handshake completion.

3 weeks agoMINOR: mux-quic: set expect data only on frontend side
Amaury Denoyelle [Tue, 10 Jun 2025 14:37:11 +0000 (16:37 +0200)] 
MINOR: mux-quic: set expect data only on frontend side

Stream data layer is notified that data is expected when FIN is
received, which marks the end of the HTTP request. This prepares data
layer to be able to handle the expected HTTP response.

Thus, this step is only relevant on frontend side. On backend side, FIN
marks the end of the HTTP response. No further content is expected, thus
expect data should not be set in this case.

Note that se_expect_data() invokation via qcs_attach_sc() is not
protected. This is because this function will only be called during
request headers parsing which is performed on the frontend side.

3 weeks agoMINOR: mux-quic: define flag for backend side
Amaury Denoyelle [Wed, 11 Jun 2025 09:30:24 +0000 (11:30 +0200)] 
MINOR: mux-quic: define flag for backend side

Mux connection is flagged with new QC_CF_IS_BACK if used on the backend
side. For now the only change is during traces, to be able to
differentiate frontend and backend usage.

3 weeks agoMINOR: mux-quic: improve documentation for snd/rcv app-ops
Amaury Denoyelle [Tue, 10 Jun 2025 14:36:54 +0000 (16:36 +0200)] 
MINOR: mux-quic: improve documentation for snd/rcv app-ops

Complete document for rcv_buf/snd_buf operations. In particular, return
value is now explicitely defined. For H3 layer, associated functions
documentation is also extended.

3 weeks agoMINOR: quic: mark ctrl layer as ready on quic_connect_server()
Amaury Denoyelle [Thu, 5 Jun 2025 13:27:49 +0000 (15:27 +0200)] 
MINOR: quic: mark ctrl layer as ready on quic_connect_server()

Use conn_ctrl_init() on the connection when quic_connect_server()
succeeds. This is necessary so that the connection is considered as
completely initialized. Without this, connect operation will be call
again if connection is reused.

3 weeks agoMEDIUM: backend: delay MUX init with ALPN even if proto is forced
Amaury Denoyelle [Wed, 28 May 2025 15:05:44 +0000 (17:05 +0200)] 
MEDIUM: backend: delay MUX init with ALPN even if proto is forced

On backend side, multiplexer layer is initialized during
connect_server(). However, this step is not performed if ALPN is used,
as the negotiated protocol may be unknown. Multiplexer initialization is
delayed after TLS handshake completion.

There are still exceptions though that forces the MUX to be initialized
even if ALPN is used. One of them was if <mux_proto> server field was
already set at this stage, which is the case when an explicit proto is
selected on the server line configuration. Remove this condition so that
now MUX init is delayed with ALPN even if proto is forced.

The scope of this change should be minimal. In fact, the only impact
concerns server config with both proto and ALPN set, which is pretty
unlikely as it is contradictory.

The main objective of this patch is to prepare QUIC support on the
backend side. Indeed, QUIC proto will be forced on the server if a QUIC
address is used, similarly to bind configuration. However, we still want
to delay MUX initialization after QUIC handshake completion. This is
mandatory to know the selected application protocol, required during
QUIC MUX init.

3 weeks agoBUG/MEDIUM: mux-quic: adjust wakeup behavior
Amaury Denoyelle [Tue, 3 Jun 2025 15:18:30 +0000 (17:18 +0200)] 
BUG/MEDIUM: mux-quic: adjust wakeup behavior

Change wake callback behavior for QUIC MUX. This operation loops over
each QCS and notify their stream data layer on certain events via
internal helper qcc_wake_some_streams().

Previously, streams were notified only if an error occured on the
connection. Change this to notify streams data layer everytime wake
callback is used. This behavior is now identical to H2 MUX.

qcc_wake_some_streams() is also renamed to qcc_wake_streams(), as it
better reflect its true behavior.

This change should not have performance impact as wake mux ops should
not be called frequently. Note that qcc_wake_streams() can also be
called directly via qcc_io_process() to ensure a new error is correctly
propagated. As wake callback first uses qcc_io_process(), it will only
call qcc_wake_streams() if no error is present.

No known issue is associated with this commit. However, it could prevent
freezing transfer under certain condition. As such, it is considered as
a bug fix worthy of backporting.

This should be backported after a period of observation.

3 weeks agoBUILD: hlua: Fix warnings about uninitialized variables (2)
Christopher Faulet [Thu, 12 Jun 2025 08:49:51 +0000 (10:49 +0200)] 
BUILD: hlua: Fix warnings about uninitialized variables (2)

It was still failing on Ubuntu-24.04 with GCC+ASAN. So, instead of
understand the code path the compiler followed to report uninitialized
variables, let's init them now.

No backport needed.

3 weeks agoBUILD: listener: fix 'for' loop inline variable declaration
Aurelien DARRAGON [Wed, 11 Jun 2025 17:41:38 +0000 (19:41 +0200)] 
BUILD: listener: fix 'for' loop inline variable declaration

commit 16eb0fab3 ("MAJOR: counters: dispatch counters over thread groups")
introduced a build regression on some compilers:

  src/listener.c: In function 'listener_accept':
  src/listener.c:1095:3: error: 'for' loop initial declarations are only allowed in C99 mode
     for (int it = 0; it < global.nbtgroups; it++)
     ^
  src/listener.c:1095:3: note: use option -std=c99 or -std=gnu99 to compile your code
  src/listener.c:1101:4: error: 'for' loop initial declarations are only allowed in C99 mode
      for (int it = 0; it < global.nbtgroups; it++) {
      ^
  make: *** [src/listener.o] Error 1
  make: *** Waiting for unfinished jobs....

Let's fix that.
No backport needed

3 weeks agoBUILD: hlua: Fix warnings about uninitialized variables
Christopher Faulet [Thu, 12 Jun 2025 06:42:18 +0000 (08:42 +0200)] 
BUILD: hlua: Fix warnings about uninitialized variables

In hlua_applet_tcp_recv_try() and hlua_applet_tcp_getline_yield(), GCC 14.2
reports warnings about 'blk2' variable that may be used uninitialized. It is
a bit strange because the code is pretty similar than before. But to make it
happy and to avoid bugs if the API change in future, 'blk2' is now used only
when its length is greater than 0.

No need to backport.

3 weeks agoBUG/MINOR: hlua: Don't forget the return statement after a hlua_yieldk()
Christopher Faulet [Wed, 11 Jun 2025 19:39:19 +0000 (21:39 +0200)] 
BUG/MINOR: hlua: Don't forget the return statement after a hlua_yieldk()

In hlua_applet_tcp_getline_yield(), the function may yield if there is no
data available. However we must take care to add a return statement just
after the call to hlua_yieldk(). I don't know the details of the LUA API,
but at least, this return statement fix a build error about uninitialized
variables that may be used.

It is a 3.3-specific issue. No backport needed.

3 weeks agoMEDIUM: quic-be: initialize MUX on handshake completion
Frederic Lecaille [Thu, 11 Jan 2024 18:05:55 +0000 (19:05 +0100)] 
MEDIUM: quic-be: initialize MUX on handshake completion

On backend side, MUX is instantiated after QUIC handshake completion.
This step is performed via qc_ssl_provide_quic_data(). First, connection
flags for handshake completion are resetted. Then, MUX is instantiated
via conn_create_mux() function.

3 weeks agoMINOR: quic: define proper proto on QUIC servers
Amaury Denoyelle [Thu, 5 Jun 2025 13:18:44 +0000 (15:18 +0200)] 
MINOR: quic: define proper proto on QUIC servers

Force QUIC as <mux_proto> for server if a QUIC address is used. This is
similarly to what is already done for bind instances on the frontend
side. This step ensures that conn_create_mux() will select the proper
protocol.

3 weeks agoMINOR: quic-be: Prevent the MUX to send/receive data
Frederic Lecaille [Fri, 5 Jan 2024 14:45:17 +0000 (15:45 +0100)] 
MINOR: quic-be: Prevent the MUX to send/receive data

Such actions must be interrupted until the handshake completion.

3 weeks agoMINOR: quic-be: get rid of ->li quic_conn member
Frederic Lecaille [Fri, 6 Jun 2025 13:20:00 +0000 (15:20 +0200)] 
MINOR: quic-be: get rid of ->li quic_conn member

Replace ->li quic_conn pointer to struct listener member by  ->target which is
an object type enum and adapt the code.
Use __objt_(listener|server)() where the object type is known. Typically
this is were the code which is specific to one connection type (frontend/backend).
Remove <server> parameter passed to qc_new_conn(). It is redundant with the
<target> parameter.
GSO is not supported at this time for QUIC backend. qc_prep_pkts() is modified
to prevent it from building more than an MTU. This has as consequence to prevent
qc_send_ppkts() to use GSO.
ssl_clienthello.c code is run only by listeners. This is why __objt_listener()
is used in place of ->li.

3 weeks agoMINOR: quic-be: SSL_get_peer_quic_transport_params() not defined by OpenSSL 3.5 QUIC API
Frederic Lecaille [Mon, 2 Jun 2025 07:04:52 +0000 (09:04 +0200)] 
MINOR: quic-be: SSL_get_peer_quic_transport_params() not defined by OpenSSL 3.5 QUIC API

Disable the code around SSL_get_peer_quic_transport_params() as this was done
for USE_QUIC_OPENSSL_COMPAT because SSL_get_peer_quic_transport_params() is not
defined by OpenSSL 3.5 QUIC API.

3 weeks agoMINOR: quic-be: Make the secret derivation works for QUIC backends (USE_QUIC_OPENSSL_...
Frederic Lecaille [Wed, 28 May 2025 14:30:41 +0000 (16:30 +0200)] 
MINOR: quic-be: Make the secret derivation works for QUIC backends (USE_QUIC_OPENSSL_COMPAT)

quic_tls_compat_keylog_callback() is the callback used by the QUIC OpenSSL
compatibility module to derive the TLS secrets from other secrets provided
by keylog. The <write> local variable to this function is initialized to denote
the direction (write to send, read to receive) the secret is supposed to be used
for. That said, as the QUIC cryptographic algorithms are symmetrical, the
direction is inversed between the peer: a secret which is used to write/send/cipher
data from a peer point of view is also the secret which is used to
read/receive/decipher data. This was confirmed by the fact that without this
patch, the TLS stack first provides the peer with Handshake to send/cipher
data. The client could not use such secret to decipher the Handshake packets
received from the server. This patch simply reverse the direction stored by
<write> variable to make the secrets derivation works for the QUIC client.

3 weeks agoMINOR: quic-be: Missing callbacks initializations (USE_QUIC_OPENSSL_COMPAT)
Frederic Lecaille [Wed, 28 May 2025 13:58:44 +0000 (15:58 +0200)] 
MINOR: quic-be: Missing callbacks initializations (USE_QUIC_OPENSSL_COMPAT)

quic_tls_compat_init() function is called from OpenSSL QUIC compatibility module
(USE_QUIC_OPENSSL_COMPAT) to initialize the keylog callback and the callback
which stores the QUIC transport parameters as a TLS extensions into the stack.
These callbacks must also be initialized for QUIC backends.

3 weeks agoMINOR: quic-be: Store the remote transport parameters asap
Frederic Lecaille [Wed, 17 Jan 2024 14:30:04 +0000 (15:30 +0100)] 
MINOR: quic-be: Store the remote transport parameters asap

This is done from TLS secrets derivation callback at Application level (the last
encryption level) calling SSL_get_peer_quic_transport_params() to have an access
to the TLS transport paremeters extension embedded into the Server Hello TLS message.
Then, quic_transport_params_store() is called to store a decoded version of
these transport parameters.

3 weeks agoMINOR: quic-be: I/O handler switch adaptation
Frederic Lecaille [Tue, 16 Jan 2024 09:30:13 +0000 (10:30 +0100)] 
MINOR: quic-be: I/O handler switch adaptation

For connection to QUIC servers, this patch modifies the moment where the I/O
handler callback is switched to quic_conn_app_io_cb(). This is no more
done as for listener just after the handshake has completed but just after
it has been confirmed.

3 weeks agoMINOR: quic-be: Initial packet number space discarding.
Frederic Lecaille [Fri, 12 Jan 2024 16:03:02 +0000 (17:03 +0100)] 
MINOR: quic-be: Initial packet number space discarding.

Discard the Initial packet number space as soon as possible. This is done
during handshakes in quic_conn_io_cb() as soon as an Handshake packet could
be successfully sent.

3 weeks agoMINOR: quic-be: Add the conn object to the server SSL context
Frederic Lecaille [Tue, 27 May 2025 09:29:30 +0000 (11:29 +0200)] 
MINOR: quic-be: Add the conn object to the server SSL context

The initialization of <ssl_app_data_index> SSL user data index is required
to make all the SSL sessions to QUIC servers work as this is done for TCP
servers. The conn object notably retrieve for SSL callback which are
server specific (e.g. ssl_sess_new_srv_cb()).

3 weeks agoMINOR: quic-be: Build post handshake frames
Frederic Lecaille [Fri, 12 Jan 2024 15:23:55 +0000 (16:23 +0100)] 
MINOR: quic-be: Build post handshake frames

This action is not specific to listeners. A QUIC client also have to send
NEW_CONNECTION_ID frames.

3 weeks agoMINOR: quic-be: Store asap the DCID
Frederic Lecaille [Fri, 12 Jan 2024 13:39:08 +0000 (14:39 +0100)] 
MINOR: quic-be: Store asap the DCID

Store the peer connection ID (SCID) as the connection DCID as soon as an Initial
packet is received.
Stop comparing the packet to QUIC_PACKET_TYPE_0RTT is already match as
QUIC_PACKET_TYPE_INITIAL.
A QUIC server must not send too short datagram with ack-eliciting packets inside.
This cannot be done from quic_rx_pkt_parse() because one does not know if
there is ack-eliciting frame into the Initial packets. If the packet must be
dropped, this is after having parsed it!

3 weeks agoMINOR: h3-be: Correctly retrieve h3 counters
Frederic Lecaille [Thu, 11 Jan 2024 18:17:56 +0000 (19:17 +0100)] 
MINOR: h3-be: Correctly retrieve h3 counters

This is done using qc_counters() function which supports also QUIC servers.

3 weeks agoMINOR: quic-be: Handshake packet number space discarding
Frederic Lecaille [Thu, 11 Jan 2024 18:12:20 +0000 (19:12 +0100)] 
MINOR: quic-be: Handshake packet number space discarding

This is done for QUIC clients (or haproxy QUIC servers) when the handshake is
confirmed.

3 weeks agoMINOR: quic-be: Datagrams and packet parsing support
Frederic Lecaille [Wed, 10 Jan 2024 15:48:51 +0000 (16:48 +0100)] 
MINOR: quic-be: Datagrams and packet parsing support

Modify quic_dgram_parse() to stop passing it a listener as third parameter.
In place the object type address of the connection socket owner is passed
to support the haproxy servers with QUIC as transport protocol.
qc_owner_obj_type() is implemented to return this address.
qc_counters() is also implemented to return the QUIC specific counters of
the proxy of owner of the connection.
quic_rx_pkt_parse() called by quic_dgram_parse() is also modify to use
the object type address used by this latter as last parameter. It is
also modified to send Retry packet only from listeners. A QUIC client
(connection to haproxy QUIC servers) must drop the Initial packets with
non null token length. It is also not supposed to receive O-RTT packets
which are dropped.

3 weeks agoMINOR: quic-be: Do not redispatch the datagrams
Frederic Lecaille [Wed, 10 Jan 2024 10:10:36 +0000 (11:10 +0100)] 
MINOR: quic-be: Do not redispatch the datagrams

The QUIC datagram redispatch is there to counter the race condition which
exists only for QUIC connections to listener where datagrams may arrive
on the wrong socket between the bind() and connect() calls.
Run this code part only for listeners.

3 weeks agoMINOR: quic-be: add field for max_udp_payload_size into quic_conn
Frederic Lecaille [Thu, 5 Jun 2025 12:58:50 +0000 (14:58 +0200)] 
MINOR: quic-be: add field for max_udp_payload_size into quic_conn

Add ->max_udp_payload_size new member to quic_conn struct.
Initialize it from qc_new_conn().
Adapt qc_snd_buf() to use it.

3 weeks agoMINOR: quic-be: xprt ->init() adapatations
Frederic Lecaille [Tue, 19 Dec 2023 06:58:48 +0000 (07:58 +0100)] 
MINOR: quic-be: xprt ->init() adapatations

Allocate a connection to connect to QUIC servers from qc_conn_init() which is the
->init() QUIC xprt callback.
Also initialize ->prepare_srv and ->destroy_srv callback as this done for TCP
servers.

3 weeks agoMINOR: quic-be: QUIC connection allocation adaptation (qc_new_conn())
Frederic Lecaille [Fri, 5 Jan 2024 15:32:42 +0000 (16:32 +0100)] 
MINOR: quic-be: QUIC connection allocation adaptation (qc_new_conn())

For haproxy QUIC servers (or QUIC clients), the peer is considered as validated.
This is a property which is more specific to QUIC servers (haproxy QUIC listeners).
No <odcid> is used for the QUIC client connection. It is used only on the QUIC server side.
The <token_odcid> is also not used on the QUIC client side. It must be embedded into
the transport parameters only on the QUIC server side.
The quic_conn is created before the socket allocation. So, the local address is
zeroed.
Initilize the transport parameter with qc_srv_params_init().
Stop hardcoding the <server> parameter passed value to qc_new_isecs() to correctly
initialize the Initial secrets.

3 weeks agoMINOR: quic-be: ->connect() protocol callback adaptations
Frederic Lecaille [Fri, 5 Jan 2024 15:23:33 +0000 (16:23 +0100)] 
MINOR: quic-be: ->connect() protocol callback adaptations

Modify quic_connect_server() which is the ->connect() callback for QUIC protocol:
    - add a BUG_ON() run when entering this funtion: the <fd> socket must equal -1
    - conn->handle is a union. conn->handle.qc is use for QUIC connection,
      conn->handle.fd must not be used to store the fd.
    - code alignment fix for setsockopt(fd, SOL_SOCKET, (SO_SNDBUF|SO_RCVBUF))
  statements
    - remove the section of code which was duplicated from ->connect() TCP callback
    - fd_insert() the new socket file decriptor created to connect to the QUIC
      server with quic_conn_sock_fd_iocb() as callback for read event.

3 weeks agoMINOR: sock: Add protocol and socket types parameters to sock_create_server_socket()
Frederic Lecaille [Tue, 3 Jun 2025 14:25:53 +0000 (16:25 +0200)] 
MINOR: sock: Add protocol and socket types parameters to sock_create_server_socket()

This patch only adds <proto_type> new proto_type enum parameter and <sock_type>
socket type parameter to sock_create_server_socket() and adapts its callers.
This is to prepare the use of this function by QUIC servers/backends.

3 weeks agoMINOR: quic-be: Add a function to initialize the QUIC client transport parameters
Frederic Lecaille [Wed, 3 Jan 2024 13:36:44 +0000 (14:36 +0100)] 
MINOR: quic-be: Add a function to initialize the QUIC client transport parameters

Implement qc_srv_params_init() to initialize the QUIC client transport parameters
in relation with connections to haproxy servers/backends.

3 weeks agoMINOR: quic-be: SSL sessions initializations
Frederic Lecaille [Tue, 19 Dec 2023 07:16:42 +0000 (08:16 +0100)] 
MINOR: quic-be: SSL sessions initializations

Modify qc_alloc_ssl_sock_ctx() to pass the connection object as parameter. It is
NULL for a QUIC listener, not NULL for a QUIC server. This connection object is
set as value for ->conn quic_conn struct member. Initialise the SSL session object from
this function for QUIC servers.
qc_ssl_set_quic_transport_params() is also modified to pass the SSL object as parameter.
This is the unique parameter this function needs. <qc> parameter is used only for
the trace.
SSL_do_handshake() must be calle as soon as the SSL object is initialized for
the QUIC backend connection. This triggers the TLS CRYPTO data delivery.
tasklet_wakeup() is also called to send asap these CRYPTO data.
Modify the QUIC_EV_CONN_NEW event trace to dump the potential errors returned by
SSL_do_handshake().

3 weeks agoMINOR: quic-be: ssl_sock contexts allocation and misc adaptations
Frederic Lecaille [Mon, 18 Dec 2023 16:26:01 +0000 (17:26 +0100)] 
MINOR: quic-be: ssl_sock contexts allocation and misc adaptations

Implement ssl_sock_new_ssl_ctx() to allocate a SSL server context as this is currently
done for TCP servers and also for QUIC servers depending on the <is_quic> boolean value
passed as new parameter. For QUIC servers, this function calls ssl_quic_srv_new_ssl_ctx()
which is specific to QUIC.

3 weeks agoMINOR: quic-be: Correct the QUIC protocol lookup
Frederic Lecaille [Mon, 18 Dec 2023 16:11:27 +0000 (17:11 +0100)] 
MINOR: quic-be: Correct the QUIC protocol lookup

From connect_server(), QUIC protocol could not be retreived by protocol_lookup()
because of the PROTO_TYPE_STREAM default passed as argument. In place to support
QUIC srv->addr_type.proto_type may be safely passed.

3 weeks agoMINOR: quic-be: Add a function for the TLS context allocations
Frederic Lecaille [Mon, 18 Dec 2023 16:06:40 +0000 (17:06 +0100)] 
MINOR: quic-be: Add a function for the TLS context allocations

Implement ssl_quic_srv_new_ssl_ctx() whose aim is to allocate a TLS context
for QUIC servers.

3 weeks agoMINOR: quic-be: QUIC server xprt already set when preparing their CTXs
Frederic Lecaille [Mon, 18 Dec 2023 13:25:53 +0000 (14:25 +0100)] 
MINOR: quic-be: QUIC server xprt already set when preparing their CTXs

The QUIC servers xprts have already been set at server line parsing time.
This patch prevents the QUIC servers xprts to be reset to <ssl_sock> value which is
the value used for SSL/TCP connections.

3 weeks agoMINOR: quic-be: QUIC backend XPRT and transport parameters init during parsing
Frederic Lecaille [Mon, 18 Dec 2023 10:18:45 +0000 (11:18 +0100)] 
MINOR: quic-be: QUIC backend XPRT and transport parameters init during parsing

Add ->quic_params new member to server struct.
Also set the ->xprt member of the server being initialized and initialize asap its
transport parameters from _srv_parse_init().

3 weeks agoMINOR: quic-be: Call ->prepare_srv() callback at parsing time
Frederic Lecaille [Mon, 18 Dec 2023 09:59:15 +0000 (10:59 +0100)] 
MINOR: quic-be: Call ->prepare_srv() callback at parsing time

This XPRT callback is called from check_config_validity() after the configuration
has been parsed to initialize all the SSL server contexts.

This patch implements the same thing for the QUIC servers.

3 weeks agoMINOR: quic-be: Version Information transport parameter check
Frederic Lecaille [Wed, 17 Jan 2024 17:14:44 +0000 (18:14 +0100)] 
MINOR: quic-be: Version Information transport parameter check

Add a little check to verify that the version chosen by the server matches
with the client one. Initiliazes local transport parameters ->negotiated_version
value with this version if this is the case. If not, return 0;

3 weeks agoMINOR: quic-be: Correct Version Information transp. param encoding
Frederic Lecaille [Wed, 17 Jan 2024 16:17:26 +0000 (17:17 +0100)] 
MINOR: quic-be: Correct Version Information transp. param encoding

According to the RFC, a QUIC client must encode the QUIC version it supports
into the "Available Versions" of "Version Information" transport parameter
order by descending preference.

This is done defining <quic_version_2> and <quic_version_draft_29> new variables
pointers to the corresponding version of <quic_versions> array elements.
A client announces its available versions as follows: v1, v2, draft29.

3 weeks agoMINOR: mux-quic-be: allow QUIC proto on backend side
Amaury Denoyelle [Wed, 11 Jun 2025 15:38:21 +0000 (17:38 +0200)] 
MINOR: mux-quic-be: allow QUIC proto on backend side

Activate QUIC protocol support for MUX-QUIC on the backend side,
additionally to current frontend support. This change is mandatory to be
able to implement QUIC on the backend side.

Without this modification, it is impossible to activate explicitely QUIC
protocol on a server line, hence an error is reported :
  config : proxy 'xxxx' : MUX protocol 'quic' is not usable for server 'yyyy'

3 weeks agoMINOR: server: mark QUIC support as experimental
Amaury Denoyelle [Wed, 11 Jun 2025 15:26:44 +0000 (17:26 +0200)] 
MINOR: server: mark QUIC support as experimental

Mark QUIC address support for servers as experimental on the backend
side. Previously, it was allowed but wouldn't function as expected. As
QUIC backend support requires several changes, it is better to declare
it as experimental first.

3 weeks agoMINOR: server: implement helper to identify QUIC servers
Amaury Denoyelle [Wed, 11 Jun 2025 15:28:46 +0000 (17:28 +0200)] 
MINOR: server: implement helper to identify QUIC servers

Define srv_is_quic() which can be used to quickly identified if a server
uses QUIC protocol.

3 weeks agoBUG/MINOR: config/server: reject QUIC addresses
Amaury Denoyelle [Wed, 11 Jun 2025 16:26:10 +0000 (18:26 +0200)] 
BUG/MINOR: config/server: reject QUIC addresses

QUIC is not implemented on the backend side. To prevent any issue, it is
better to reject any server configured which uses it. This is done via
_srv_parse_init() which is used both for static and dynamic servers.

This should be backported up to all stable versions.

3 weeks ago[RELEASE] Released version 3.3-dev1 v3.3-dev1
Christopher Faulet [Wed, 11 Jun 2025 12:31:33 +0000 (14:31 +0200)] 
[RELEASE] Released version 3.3-dev1

Released version 3.3-dev1 with the following main changes :
    - BUILD: tools: properly define ha_dump_backtrace() to avoid a build warning
    - DOC: config: Fix a typo in 2.7 (Name format for maps and ACLs)
    - REGTESTS: Do not use REQUIRE_VERSION for HAProxy 2.5+ (5)
    - REGTESTS: Remove REQUIRE_VERSION=2.3 from all tests
    - REGTESTS: Remove REQUIRE_VERSION=2.4 from all tests
    - REGTESTS: Remove tests with REQUIRE_VERSION_BELOW=2.4
    - REGTESTS: Remove support for REQUIRE_VERSION and REQUIRE_VERSION_BELOW
    - MINOR: server: group postinit server tasks under _srv_postparse()
    - MINOR: stats: add stat_col flags
    - MINOR: stats: add ME_NEW_COMMON() helper
    - MINOR: proxy: collect per-capability stat in proxy_cond_disable()
    - MINOR: proxy: add a true list containing all proxies
    - MINOR: log: only run postcheck_log_backend() checks on backend
    - MEDIUM: proxy: use global proxy list for REGISTER_POST_PROXY_CHECK() hook
    - MEDIUM: server: automatically add server to proxy list in new_server()
    - MEDIUM: server: add and use srv_init() function
    - BUG/MAJOR: leastconn: Protect tree_elt with the lbprm lock
    - BUG/MEDIUM: check: Requeue healthchecks on I/O events to handle check timeout
    - CLEANUP: applet: Update comment for applet_put* functions
    - DEBUG: check: Add the healthcheck's expiration date in the trace messags
    - BUG/MINOR: mux-spop: Fix null-pointer deref on SPOP stream allocation failure
    - CLEANUP: sink: remove useless cleanup in sink_new_from_logger()
    - MAJOR: counters: add shared counters base infrastructure
    - MINOR: counters: add shared counters helpers to get and drop shared pointers
    - MINOR: counters: add common struct and flags to {fe,be}_counters_shared
    - MEDIUM: counters: manage shared counters using dedicated helpers
    - CLEANUP: counters: merge some common counters between {fe,be}_counters_shared
    - MINOR: counters: add local-only internal rates to compute some maxes
    - MAJOR: counters: dispatch counters over thread groups
    - BUG/MEDIUM: cli: Properly parse empty lines and avoid crashed
    - BUG/MINOR: config: emit warning for empty args only in discovery mode
    - BUG/MINOR: config: fix arg number reported on empty arg warning
    - BUG/MINOR: quic: Missing SSL session object freeing
    - MINOR: applet: Add API functions to manipulate input and output buffers
    - MINOR: applet: Add API functions to get data from the input buffer
    - CLEANUP: applet: Simplify a bit comments for applet_put* functions
    - MEDIUM: hlua: Update TCP applet functions to use the new applet API
    - BUG/MEDIUM: fd: Use the provided tgid in fd_insert() to get tgroup_info
    - BUG/MINIR: h1: Fix doc of 'accept-unsafe-...-request' about URI parsing

3 weeks agoBUG/MINIR: h1: Fix doc of 'accept-unsafe-...-request' about URI parsing
Christopher Faulet [Tue, 10 Jun 2025 17:03:44 +0000 (19:03 +0200)] 
BUG/MINIR: h1: Fix doc of 'accept-unsafe-...-request' about URI parsing

The description of tests performed on the URI in H1 when
'accept-unsafe-violations-in-http-request' option is wrong. It states that
only characters below 32 and 127 are blocked when this option is set,
suggesting that otherwise, when it is not set, all invalid characters in the
URI, according to the RFC3986, are blocked.

But in fact, it is not true. By default all character below 32 and above 127
are blocked. And when 'accept-unsafe-violations-in-http-request' option is
set, characters above 127 (excluded) are accepted. But characters in
(33..126) are never checked, independently of this option.

This patch should fix the issue #2906. It should be backported as far as
3.0. For older versions, the docuementation could also be clarified because
this part is not really clear.

Note the request URI validation is still under discution because invalid
characters in (33.126) are never checked and some users request a stricter
parsing.

3 weeks agoBUG/MEDIUM: fd: Use the provided tgid in fd_insert() to get tgroup_info
Olivier Houchard [Tue, 10 Jun 2025 12:39:22 +0000 (12:39 +0000)] 
BUG/MEDIUM: fd: Use the provided tgid in fd_insert() to get tgroup_info

In fd_insert(), use the provided tgid to ghet the thread group info,
instead of using the one of the current thread, as we may call
fd_insert() from a thread of another thread group, that will happen at
least when binding the listeners. Otherwise we'd end up accessing the
thread mask containing enabled thread of the wrong thread group, which
can lead to crashes if we're binding on threads not present in the
thread group.
This should fix Github issue #2991.

This should be backported up to 2.8.

3 weeks agoMEDIUM: hlua: Update TCP applet functions to use the new applet API
Christopher Faulet [Thu, 5 Jun 2025 13:45:42 +0000 (15:45 +0200)] 
MEDIUM: hlua: Update TCP applet functions to use the new applet API

The functions responsible to extract data from the applet input buffer or to
push data into the applet output buffer are now relying on the newly added
functions in the applet API. This simplifies a bit the code.

3 weeks agoCLEANUP: applet: Simplify a bit comments for applet_put* functions
Christopher Faulet [Thu, 5 Jun 2025 13:43:53 +0000 (15:43 +0200)] 
CLEANUP: applet: Simplify a bit comments for applet_put* functions

Instead of repeating which buffer is used depending on the API used by the
applet, a reference to applet_get_outbuf() was added.

3 weeks agoMINOR: applet: Add API functions to get data from the input buffer
Christopher Faulet [Thu, 5 Jun 2025 13:28:45 +0000 (15:28 +0200)] 
MINOR: applet: Add API functions to get data from the input buffer

There was already functions to pushed data from the applet to the stream by
inserting them in the right buffer, depending the applet was using or not
the legacy API. Here, functions to retreive data pushed to the applet by the
stream were added:

  * applet_getchar   : Gets one character

  * applet_getblk    : Copies a full block of data

  * applet_getword   : Copies one text block representing a word using a
                       custom separator as delimiter

  * applet_getline   : Copies one text line

  * applet_getblk_nc : Get one or two blocks of data

  * applet_getword_nc: Gets one or two blocks of text representing a word
                       using a custom separator as delimiter

  * applet_getline_nc: Gets one or two blocks of text representing a line

3 weeks agoMINOR: applet: Add API functions to manipulate input and output buffers
Christopher Faulet [Thu, 5 Jun 2025 13:01:43 +0000 (15:01 +0200)] 
MINOR: applet: Add API functions to manipulate input and output buffers

In this patch, some functions were added to ease input and output buffers
manipulation, regardless the corresponding applet is using its own buffers
or it is relying on channels buffers. Following functions were added:

  * applet_get_inbuf  : Get the buffer containing data pushed to the applet
                        by the stream

  * applet_get_outbuf : Get the buffer containing data pushed by the applet
                        to the stream

  * applet_input_data : Return the amount of data in the input buffer

  * applet_skip_input : Skips <len> bytes from the input buffer

  * applet_reset_input: Skips all bytes from the input buffer

  * applet_output_room: Returns the amout of space available at the output
                        buffer

  * applet_need_room  : Indicates that the applet have more data to deliver
                        and it needs more room in the output buffer to do
so

4 weeks agoBUG/MINOR: quic: Missing SSL session object freeing
Frederic Lecaille [Wed, 4 Jun 2025 09:49:14 +0000 (11:49 +0200)] 
BUG/MINOR: quic: Missing SSL session object freeing

qc_alloc_ssl_sock_ctx() allocates an SSL_CTX object for each connection. It also
allocates an SSL object. When this function failed, it freed only the SSL_CTX object.
The correct way to free both of them is to call qc_free_ssl_sock_ctx().

Must be backported as far as 2.6.

4 weeks agoBUG/MINOR: config: fix arg number reported on empty arg warning
Amaury Denoyelle [Wed, 4 Jun 2025 13:36:13 +0000 (15:36 +0200)] 
BUG/MINOR: config: fix arg number reported on empty arg warning

If an empty argument is used in configuration, for example due to an
undefined environment variable, the rest of the line is not parsed. As
such, a warning is emitted to report this.

The warning was not totally correct as it reported the wrong argument
index. Fix this by this patch. Note that there is still an issue with
the "^" indicator, but this is not as easy to fix yet.

This is related to github issue #2995.

This should be backported up to 3.2.

4 weeks agoBUG/MINOR: config: emit warning for empty args only in discovery mode
Amaury Denoyelle [Wed, 4 Jun 2025 09:26:27 +0000 (11:26 +0200)] 
BUG/MINOR: config: emit warning for empty args only in discovery mode

Hide warning about empty argument outside of discovery mode. This is
necessary, else the message will be displayed twice, which hampers
haproxy output lisibility.

This should fix github isue #2995.

This should be backported up to 3.2.

4 weeks agoBUG/MEDIUM: cli: Properly parse empty lines and avoid crashed
Christopher Faulet [Thu, 5 Jun 2025 08:41:46 +0000 (10:41 +0200)] 
BUG/MEDIUM: cli: Properly parse empty lines and avoid crashed

Empty lines was not properly parsed and could lead to crashes because the
last argument was parsed outside of the cmdline buffer. Indeed, the last
argument is parsed to look for an eventual payload pattern. It is started
one character after the newline at the end of the command line. But it is
only valid for an non-empty command line.

So, now, this case is properly detected when we leave if an empty line is
detected.

This patch must be backported to 3.2.

4 weeks agoMAJOR: counters: dispatch counters over thread groups
Aurelien DARRAGON [Thu, 15 May 2025 17:55:11 +0000 (19:55 +0200)] 
MAJOR: counters: dispatch counters over thread groups

Most fe and be counters are good candidates for being shared between
processes. They are now grouped inside "shared" struct sub member under
be_counters and fe_counters.

Now they are properly identified, they would greatly benefit from being
shared over thread groups to reduce the cost of atomic operations when
updating them. For this, we take the current tgid into account so each
thread group only updates its own counters. For this to work, it is
mandatory that the "shared" member from {fe,be}_counters is initialized
AFTER global.nbtgroups is known, because each shared counter causes the stat
to be allocated lobal.nbtgroups times. When updating a counter without
concurrency, the first counter from the array may be updated.

To consult the shared counters (which requires aggregation of per-tgid
individual counters), some helper functions were added to counter.h to
ease code maintenance and avoid computing errors.

4 weeks agoMINOR: counters: add local-only internal rates to compute some maxes
Aurelien DARRAGON [Wed, 28 May 2025 10:00:49 +0000 (12:00 +0200)] 
MINOR: counters: add local-only internal rates to compute some maxes

cps_max (max new connections received per second), sps_max (max new
sessions per second) and http.rps_max (maximum new http requests per
second) all rely on shared counters (namely conn_per_sec, sess_per_sec and
http.req_per_sec). The problem is that shared counters are about to be
distributed over thread groups, and we cannot afford to compute the
total (for all thread groups) each time we update the max counters.

Instead, since such max counters (relying on shared counters) are a very
few exceptions, let's add internal (sess,conn,req) per sec freq counters
that are dedicated to cps_max, sps_max and http.rps_max computing.

Thanks to that, related *_max counters shouldn't be negatively impacted
by the thread-group distribution, yet they will not benefit from it
either. Related internal freq counters are prefixed with "_" to emphasize
the fact that they should not be used for other purpose (the shared ones,
which are about to be distributed over thread groups in upcoming commits
are still available and must be used instead). The internal ones could
eventually be removed at any time if we find another way to compute the
{cps,sps,http.rps)_max counters.

4 weeks agoCLEANUP: counters: merge some common counters between {fe,be}_counters_shared
Aurelien DARRAGON [Fri, 9 May 2025 09:42:37 +0000 (11:42 +0200)] 
CLEANUP: counters: merge some common counters between {fe,be}_counters_shared

Now that we have a common struct between fe and be shared counters struct
let's perform some cleanup to merge duplicate members into the common
struct part. This will ease code maintenance.

4 weeks agoMEDIUM: counters: manage shared counters using dedicated helpers
Aurelien DARRAGON [Wed, 7 May 2025 21:42:04 +0000 (23:42 +0200)] 
MEDIUM: counters: manage shared counters using dedicated helpers

proxies, listeners and server shared counters are now managed via helpers
added in one of the previous commits.

When guid is not set (ie: when not yet assigned), shared counters pointer
is allocated using calloc() (local memory) and a flag is set on the shared
counters struct to know how to manipulate (and free it). Else if guid is
set, then it means that the counters may be shared so while for now we
don't actually use a shared memory location the API is ready for that.

The way it works, for proxies and servers (for which guid is not known
during creation), we first call counters_{fe,be}_shared_get with guid not
set, which results in local pointer being retrieved (as if we just
manually called calloc() to retrieve a pointer). Later (during postparsing)
if guid is set we try to upgrade the pointer from local to shared.

Lastly, since the memory location for some objects (proxies and servers
counters) may change from creation to postparsing, let's update
counters->last_change member directly under counters_{fe,be}_shared_get()
so we don't miss it.

No change of behavior is expected, this is only preparation work.

4 weeks agoMINOR: counters: add common struct and flags to {fe,be}_counters_shared
Aurelien DARRAGON [Fri, 9 May 2025 08:42:49 +0000 (10:42 +0200)] 
MINOR: counters: add common struct and flags to {fe,be}_counters_shared

fe_counters_shared and be_counters_shared may share some common members
since they are quite similar, so we add a common struct part shared
between the two. struct counters_shared is added for convenience as
a generic pointer to manipulate common members from fe or be shared
counters pointer.

Also, the first common member is added: shared fe and be counters now
have a flags member.

4 weeks agoMINOR: counters: add shared counters helpers to get and drop shared pointers
Aurelien DARRAGON [Tue, 6 May 2025 18:45:40 +0000 (20:45 +0200)] 
MINOR: counters: add shared counters helpers to get and drop shared pointers

create include/haproxy/counters.h and src/counters.c files to anticipate
for further helpers as some counters specific tasks needs to be carried
out and since counters are shared between multiple object types (ie:
listener, proxy, server..) we need generic helpers.

Add some shared counters helper which are not yet used but will be updated
in upcoming commits.

4 weeks agoMAJOR: counters: add shared counters base infrastructure
Aurelien DARRAGON [Tue, 8 Apr 2025 16:16:38 +0000 (18:16 +0200)] 
MAJOR: counters: add shared counters base infrastructure

Shareable counters are not tagged as shared counters and are dynamically
allocated in separate memory area as a prerequisite for being stored
in shared memory area. For now, GUID and threads groups are not taken into
account, this is only a first step.

also we ensure all counters are now manipulated using atomic operations,
namely, "last_change" counter is now read from and written to using atomic
ops.

Despite the numerous changes caused by the counters being moved away from
counters struct, no change of behavior should be expected.

4 weeks agoCLEANUP: sink: remove useless cleanup in sink_new_from_logger()
Aurelien DARRAGON [Wed, 4 Jun 2025 14:51:04 +0000 (16:51 +0200)] 
CLEANUP: sink: remove useless cleanup in sink_new_from_logger()

As reported by Ilya in GH #2994, some cleanup parts in
sink_new_from_logger() function are not used.

We can actually simplify the cleanup logic to remove dead code, let's
do that by renaming "error_final" label to "error" and only making use
of the "error" label, because sink_free() already takes care of proper
cleanup for all sink members.

4 weeks agoBUG/MINOR: mux-spop: Fix null-pointer deref on SPOP stream allocation failure
Christopher Faulet [Wed, 4 Jun 2025 06:48:48 +0000 (08:48 +0200)] 
BUG/MINOR: mux-spop: Fix null-pointer deref on SPOP stream allocation failure

When we try to allocate a new SPOP stream, if an error is encountered,
spop_strm_destroy() is called to released the eventually allocated
stream. But, it must only be called if a stream was allocated. If the
reported error is an SPOP stream allocation failure, we must just leave to
avoid null-pointer dereference.

This patch should fix point 1 of the issue #2993. It must be backported as
far as 3.1.

4 weeks agoDEBUG: check: Add the healthcheck's expiration date in the trace messags
Christopher Faulet [Tue, 3 Jun 2025 13:06:11 +0000 (15:06 +0200)] 
DEBUG: check: Add the healthcheck's expiration date in the trace messags

It could help to diagnose some issues about timeout processing. So let's add
it !

4 weeks agoCLEANUP: applet: Update comment for applet_put* functions
Christopher Faulet [Tue, 3 Jun 2025 09:06:09 +0000 (11:06 +0200)] 
CLEANUP: applet: Update comment for applet_put* functions

These functions were copied from the channel API and modified to work with
applets using the new API or the legacy one. However, the comments were
updated accordingly. It is the purpose of this patch.

4 weeks agoBUG/MEDIUM: check: Requeue healthchecks on I/O events to handle check timeout
Christopher Faulet [Tue, 3 Jun 2025 12:50:38 +0000 (14:50 +0200)] 
BUG/MEDIUM: check: Requeue healthchecks on I/O events to handle check timeout

When a healthchecks is processed, once the first wakeup passed to start the
check, and as long as the expiration timer is not reached, only I/O events
are able to wake it up. It is an issue when there is a check timeout
defined.  Especially if the connect timeout is high and the check timeout is
low. In that case, the healthcheck's task is never requeue to handle any
timeout update. When the connection is established, the check timeout is set
to replace the connect timeout. It is thus possible to report a success
while a timeout should be reported.

So, now, when an I/O event is handled, the healthcheck is requeue, except if
an success or an abort is reported.

Thanks to Thierry Fournier for report and the reproducer.

This patch must be backported to all stable versions.

5 weeks agoBUG/MAJOR: leastconn: Protect tree_elt with the lbprm lock
Olivier Houchard [Tue, 3 Jun 2025 02:37:26 +0000 (02:37 +0000)] 
BUG/MAJOR: leastconn: Protect tree_elt with the lbprm lock

In fwlc_srv_reposition(), set the server's tree_elt while we still hold
the lbprm read lock. While it was protected from concurrent
fwlc_srv_reposition() calls by the server's lb_lock, it was not from
dequeuing/requeuing that could occur if the server gets down/up or its
weight is changed, and that would lead to inconsistencies, and the
watchdog killing the process because it is stuck in an infinite loop in
fwlc_get_next_server().

This hopefully fixes github issue #2990.

This should be backported to 3.2.

5 weeks agoMEDIUM: server: add and use srv_init() function
Aurelien DARRAGON [Fri, 9 May 2025 18:27:29 +0000 (20:27 +0200)] 
MEDIUM: server: add and use srv_init() function

rename _srv_postparse() internal function to srv_init() function and group
srv_init_per_thr() plus idle conns list init inside it. This way we can
perform some simplifications as srv_init() performs multiple server
init steps after parsing.

SRV_F_CHECKED flag was added, it is automatically set when srv_init()
runs successfully. If the flag is already set and srv_init() is called
again, nothing is done. This permis to manually call srv_init() earlier
than the default POST_CHECK hook when needed without risking to do things
twice.

5 weeks agoMEDIUM: server: automatically add server to proxy list in new_server()
Aurelien DARRAGON [Fri, 9 May 2025 17:24:55 +0000 (19:24 +0200)] 
MEDIUM: server: automatically add server to proxy list in new_server()

while new_server() takes the parent proxy as argument and even assigns
srv->proxy to the parent proxy, it didn't actually inserted the server
to the parent proxy server list on success.

The result is that sometimes we add the server to the list after
new_server() is called, and sometimes we don't.

This is really error-prone and because of that hooks such as
REGISTER_POST_SERVER_CHECK() which as run for all servers listed in
all proxies may not be relied upon for servers which are not actually
inserted in their parent proxy server list. Plus it feels very strange
to have a server that points to a proxy, but then the proxy doesn't know
about it because it cannot find it in its server list.

To prevent errors and make proxy->srv list reliable, we move the insertion
logic directly under new_server(). This requires to know if we are called
during parsing or during runtime to either insert or append the server to
the parent proxy list. For that we use PR_FL_CHECKED flag from the parent
proxy (if the flag is set, then the proxy was checked so we are past the
init phase, thus we assume we are called during runtime)

This implies that during startup if new_server() has to be cancelled on
error paths we need to call srv_detach() (which is now exposed in server.h)
before srv_drop().

The consequence of this commit is that REGISTER_POST_SERVER_CHECK() should
not run reliably on all servers created using new_server() (without having
to manually loop on global servers_list)

5 weeks agoMEDIUM: proxy: use global proxy list for REGISTER_POST_PROXY_CHECK() hook
Aurelien DARRAGON [Fri, 9 May 2025 14:41:30 +0000 (16:41 +0200)] 
MEDIUM: proxy: use global proxy list for REGISTER_POST_PROXY_CHECK() hook

REGISTER_POST_PROXY_CHECK() used to iterate over "main" proxies to run
registered callbacks. This means hidden proxies (and their servers) did
not get a chance to get post-checked and could cause issues if some post-
checks are expected to be executed on all proxies no matter their type.

Instead we now rely on the global proxies list. Another side effect is that
the REGISTER_POST_SERVER_CHECK() now runs as well for servers from proxies
that are not part of the main proxies list.

5 weeks agoMINOR: log: only run postcheck_log_backend() checks on backend
Aurelien DARRAGON [Fri, 9 May 2025 14:34:27 +0000 (16:34 +0200)] 
MINOR: log: only run postcheck_log_backend() checks on backend

postcheck_log_backend() checks are executed no matter if the proxy
actually has the backend capability while the checks actually depend
on this.

Let's fix that by adding an extra condition to ensure that the BE
capability is set.

This issue is not tagged as a bug because for now it remains impossible
to have a syslog proxy without BE capability in the main proxy list, but
this may change in the future.