26933 Commits

Author SHA1 Message Date
Frederic Lecaille
fdc95fb558 MINOR: init: add HTTP client-only mode
Introduce the new <client_mode> global variable to define the operating mode
of haproxy. This variable can be set to 1 to allow haproxy to start without
any listeners.

During the initialization cycle, setting this flag ensures that the lack of
configured listeners is no longer treated as a fatal error. This allows
programs based on haproxy source code to initialize the stack and use its
features even without a frontend.
2026-04-24 11:32:45 +02:00
Frederic Lecaille
2c9d1b2b0c MINOR: hbuf: add a very lightweight hbuf API
Add a new lightweight hbuf API to buffer formatted strings, similar to the
existing buffer API (struct buffer). This is required by haterm to build
its configuration in memory (fileless mode).

Update haterm to use this new API.

Note: hstream_str_buf_append() has been renamed to hbuf_str_append().
2026-04-24 11:32:45 +02:00
Frederic Lecaille
d81c9c06a4 BUG/MEDIUM: quic: handle ECONNREFUSED on RX side
Unlike the detection performed during sendto() for an unreachable peer,
ECONNREFUSED was not handled when received via recvmsg() as an ICMP
"host unreachable" message.

This patch tracks ECONNREFUSED errors on the receive path.

Note that this detection is entirely dependent on the remote host effectively
sending an ICMP "host unreachable" message and on the absence of any network
filtering (e.g., firewalls) that would drop such ICMP packets. Without
receiving this ICMP signal, the connection state cannot be updated through
this mechanism.

At a higher level, similar to how this error is handled on sendto(),
the connection is now terminated as soon as possible by calling
qc_kill_conn(). This triggers a call to qc_notify_err(). When the mux
does not exist, it attempts to create one via conn_create_mux(). While
the latter systematically fails if the connection is flagged with
CO_FL_ERROR, it has the useful side effect of waking the stconn stream
attached to the connection during a session opening without a mux
(e.g., for H3).

This issue was caught by haload (upcoming tool).

Must be backported as far as 2.6 because it impacts both the QUIC
frontends and backends.
2026-04-24 11:32:45 +02:00
Amaury Denoyelle
cc39535702 MINOR: mux_quic: handle incomplete QMux record read
QMux implements a record layer which is used to encapsulate QUIC frames.

This patch implements reception of an incomplete record in
qcc_qstrm_recv(). BUG_ON() failures are removed and now reading will
continue until the whole record is received or a fatal error occurs.

Several adjustments were made in the logic for read operation.
Previously, read syscall was only performed if either data buffer was
empty or current record was incomplete. An extra condition is added to
perform read if there is data in the buffer but not enough to decode a
record header. Another change is that buffer realign is also performed
in this latter case and if buffer wrapping position has been reached.
2026-04-24 10:39:17 +02:00
Amaury Denoyelle
61e839c07e MINOR: mux_quic: handle conn errors on QMux without crash
Remove BUG_ON() related to connection errors when invoking XPRT
snd_buf/rcv_buf in QMux operations. Such errors are now converted in
QC_CF_ERR_CONN flag, which will disable any I/O operations and close the
connection as soon as possible.

Note that this error management is pretty crude. In particular, it could
lead to truncated data when dealing with unidirectional connection
closure from the remote peer. However, it is considered sufficient for
now to continue interop testing without being disturbed by BUG_ON()
assertion crashes.
2026-04-24 09:33:04 +02:00
Amaury Denoyelle
02bfbddce3 MINOR: mux_quic: receive MAX_STREAMS_BIDI frames in QMux
Support reception via QMux of flow control MAX-STREAMS frame for
bidirectional streams. This is similar to the QUIC with shared
qcc_recv_max_streams() function.
2026-04-24 09:33:04 +02:00
Amaury Denoyelle
64b7ef7971 MINOR: mux_quic/xprt_qstrm: simplify Rx buffer transfer
When xprt_qstrm layer is completed, MUX layer is started. Rx buffer from
the XPRT layer is transferred to the MUX so that it can handle any extra
data following the transport parameters first frame.

Since previous commit, QCC Rx buffer is dynamically allocated only when
needed. However, qmux_init() must still allocate it when there is data
to be transferred from the XPRT layer. As a result, code has been over
extended to continue to support this case.

This patch simplifies xprt_qstrm API for the Rx buffer transfer. Buffer
content and remaining record length can now be retrieved via the single
function xprt_qstrm_xfer_rxbuf(). If the buffer is empty, nothing is
performed and XPRT layer will release it. If not empty, MUX will take
ownership of the buffer from the XPRT layer.
2026-04-24 09:33:04 +02:00
Amaury Denoyelle
b8e65423f3 MINOR: mux_quic: use dynamic conn buffers for QMux
Allocate and release as needed the QCC buffers used for QMux protocol.
This should reduce the memory consumption of QMux. This is performed
both for send and receive buffers. Along with this, always free these
buffers in qcc_release() to prevent a memory leak.
2026-04-24 09:33:04 +02:00
Amaury Denoyelle
265e893921 MINOR: mux_quic: use dynamic Tx streams buffers for QMux
Improve QMux memory usage at the QCS level in accordance with the
haproxy model. The tx buffer is now allocated only when used and
released as soon as it is empty.

This change requires to extend qcc_get_stream_txbuf() for QMux. Code
part related to qc_stream_desc is protected via conn_is_quic(). A
dedicated QMux bloc is added. Similarly to QUIC, a small buf can be
allocated first.

This also requires to adapt qcc_realloc_stream_txbuf() in a similar
fashion.
2026-04-24 09:33:04 +02:00
Amaury Denoyelle
d98afae0c6 MINOR: mux_quic: refactor QMux send frames function
Clean up qcc_qstrm_send_frames(). The main change is that now return
value is clearly specified at the end of the function, depending if
everything was sent or not.
2026-04-24 09:33:04 +02:00
Amaury Denoyelle
268fd68777 MINOR: xprt_qstrm: implement close callback
Implement close callback for xprt_qstrm layer. This is called when a
connection is prematurely closed following a connect failure. Its
purpose is to clean up all xprt resources.

A special care is required for the frontend side. Indeed,
xprt_qstrm_io_cb() can call close callback via conn_create_mux() on the
latter failure. The tasklet should then immediately be stopped as the
whole xprt layer has been freed as well.
2026-04-24 09:33:04 +02:00
Amaury Denoyelle
537c90fb5e MINOR: connection: document conn_create_mux()
Function conn_create_mux() has different behavior for frontend and
backend connections. In particular, on FE side, there is a risk that the
connection is freed.

Write a comment to explain these differences clearly.
2026-04-24 09:33:04 +02:00
Amaury Denoyelle
270413aeae MINOR: xprt_qstrm: remove unused subs
Currently, xprt_qstrm does not implement subscribe mechanism. As such,
it is better for now to remove unused member <subs> for clarity.
2026-04-24 09:33:04 +02:00
Amaury Denoyelle
d7e3b826f2 BUG/MINOR: mux_quic: do not release conn on qcc_recv() for QMux
Recently, an extra check has been added so that a dead connection is
immediately release on at the end of qcc_recv() operation. This is
useful when a GOAWAY frame is received from a server, so that the
backend connection is released if idle.

This step is in fact only necessary for QUIC, as qcc_recv() is called
directly from the lower transport layer. It causes issues with QMux as
in this case qcc_recv() is called via qcc_io_recv(). A crash in this
context will occur as qcc_recv() does not indicate that a release has
been performed.

To fix this, simply disable the extra check at the end of qcc_recv() for
QMux. This is fine as in this case receive operation is always followed
by qcc_io_process() which is able to release the connection in a safe
way.

No need to backport.
2026-04-24 09:33:04 +02:00
Amaury Denoyelle
c08dcd3519 BUG/MINOR: xprt_qstrm: prevent crash if conn release on MUX wake
When QMux XPRT has successfully been able to process to transport
parameters exchange, the MUX is initialized and immediately woken up to
start transfers. However, if the connection is in an unusable state, the
latter operation will instead release the connection and all of its
network stack.

A crash would occur in case of release when finalizing the XPRT tasklet
completion. To fix this, first free every XPRT resources. MUX wake is
now conducted in a safe way as the last operation before the tasklet is
completely released.

No need to backport.
2026-04-24 09:33:04 +02:00
Amaury Denoyelle
bb016b66c4 BUG/MINOR: xprt_qstrm: ensure all local TPs are allocated
Complete initialization of xprt_qstrm layer by setting local parameters
to zero. This should prevent to emit random values to the peer.

No backport needed.
2026-04-24 09:33:04 +02:00
Amaury Denoyelle
dde5c26eb1 BUG/MINOR: mux_quic: prevent crash on qc_frm_free() with QMux
qc_frm_free() is a helper used to clean up a QUIC frame object. It is
used by MUX layer both for QUIC and QMux protocols.

This function takes a pointer to the underlying quic_conn, used only for
trace purpose. This patch fixes its usage for QMux to ensure that in
this case a NULL value is used.

No need to backport.
2026-04-24 09:31:34 +02:00
Christopher Faulet
7c4eda5b57 BUG/MEDIUM: mux-h1: Force close mode for bodyless message announcing a C-L
When dealing with EOH block, we must be sure to force the close mode for
message with no payload but annoncing a non-null content-length.

It is mainly an issue on the server side but it could be encountered on
client side too. Without this fix, a request can be switched to the DONE
state while the server is still expecting the payload. In an ideal world,
this case should not happen. But in conjunction with other bugs, it may lead
to a desynchro between haproxy and the server.

Now, when a non-null content-length is announced but we know we reached the
end of the message, we force the close mode. The only exception is for
bodyless responses (204s, 304s and responses to head requests).

Thanks to Martino Spagnuolo (r3verii) for his detailed report on this issue.

This patch must be backported to all stable version.
2026-04-23 17:06:11 +02:00
Willy Tarreau
d12edebe4a BUG/MAJOR: mux-h2: detect incomplete transfers on HEADERS frames as well
Checks are already made on H2 to detect inconsistencies between
advertised content-length and transferred data (excess of data or
premature END_STREAM flag on DATA frame). However, as found by
Martino Spagnuolo (r3verii), a subtle case remains: if the END_STREAM
appears on the HEADERS frame (i.e. a regular request for example),
then the check is not made. In this case it is possible to advertise
more contents than will really be transferred. If the other side uses
HTTP/1.1, and the server responds before the end of the transfer,
this means that the number of advertised bytes that will never be
transferred and that the server will drain will be taken from the
next request, effectively hiding a part of the header.

In practice this can be used to force subsequent requests to fail, or
when running with "http-reuse never" or when running with a totally
idle server, to perform a request smuggling by constructing specially
crafted request pairs where the first one is used to trigger an early
response and hide parts of or all headers of the second one, to
instead use a second embedded one that was not subject to analysis.

The risk remains moderate given the low prevalence of "http-reuse never"
in production environments, and of idle servers.

The fix consists in detecting if advertised content-length remains when
processing an END_STREAM flag on a HEADERS frame. It also does it for
trailers, which turn out to be another way to abuse the bug. However it
takes great care not to break bodyless responses (204, 304 and responses
to HEAD requests) that may present a content-length that doesn't reflect
the presence of a body in the response.

A temporary alternative to the fix is to disable HTTP/2 by specifying
"alpn http/1.1" on "bind" lines, and adding "option disable-h2-upgrade"
in HTTP frontends.

This must be backported to all stable versions.
2026-04-23 17:05:24 +02:00
Willy Tarreau
5a59b158ff BUG/MINOR: server: fix a possible leak of an error message in dynamic servers
In 3.4-dev6, commit de5fc2f515 ("BUG/MINOR: server: set auto SNI for
dynamic servers") allowed to properly set the SNI, and return an error
message. However the error message is leaked after being printed on the
CLI.

This should be backported to 3.3.
2026-04-23 15:10:01 +02:00
Willy Tarreau
72b5bf7285 Revert "BUG/MINOR: stream: add the newly added SF_TXN_* flags to strm_show_flags()"
This reverts commit 3c63298acdb298ed2cf18cde0b47c361ed7fdd8c.

Christopher and I had the same idea at the same moment, no need for
two fixes!
2026-04-23 14:37:33 +02:00
Willy Tarreau
4034f78fc4 BUG/MINOR: debug: properly mark the entire libs archive read-only
In 3.4-dev7, commit e1738b665d ("MINOR: debug: read all libs in memory
when set-dumpable=libs") reads dependencies into memory to store them as
a tar archive for later debugging. There was an attempt to mark the whole
archive read-only, except that the size passed in argument to mprotect()
is wrong: lib_size is only assigned after the operation and is still zero
at the moment this is done. new_size ought to be used instead.

This needs to be backported wherever the commit above is backported, at
least 3.2.
2026-04-23 13:52:33 +02:00
Willy Tarreau
3c63298acd BUG/MINOR: stream: add the newly added SF_TXN_* flags to strm_show_flags()
3 new enum values and a mask were added in latest -dev with commit
24e05fe33a ("MINOR: stream: Use a pcli transaction to replace pcli_*
members"), unfortunately the entries needed by the "flags" command were
forgotten.

No backport is needed.
2026-04-23 11:55:45 +02:00
Willy Tarreau
81e3f013a9 DOC: config: fix typo introduce in max-threads-per-group documentation
Since commit 0af603f46f ("MEDIUM: threads: change the default
max-threads-per-group value to 16"), it was written "Tha minimum" instead
of "The minimum". No backport needed, this is only in latest -dev.
2026-04-23 11:55:45 +02:00
Willy Tarreau
0b6e47354c BUG/MINOR: servers: fix last_sess date calculation
In 3.4-dev8, commit e264523112 ("MINOR: servers: Don't update last_sess
if it did not change") adjusted the last_sess date to avoid writing to
the same cache line all the time, however a typo makes it pick the wrong
second because it uses now_ms instead of now_ns (so the date would roughly
change every 12 days).

No backport needed.
2026-04-23 11:55:45 +02:00
Willy Tarreau
055726a4c9 BUG/MINOR: compression: properly disable request when setting response
In 2.8, commit ead43fe4f2 ("MEDIUM: compression: Make it so we can
compress requests as well.") added the ability to independently enable
compression on request and/or response. However there's a bug in the
"compression direction response" case, which preserves only the request
flag and adds the response direction instead of clearing the request
flag, so this directive would clear offload and make it impossible to
disable request if it was already previously enabled.

This can be backported to stable releases as far as 2.8.
2026-04-23 11:55:45 +02:00
Christopher Faulet
686f8db79b REGTESTS: Never reuse server connection in server/cli_delete_dynamic_server.vtc
A "Connection: close" header is added to responses to avoid any connection
reuse. This should avoid errors on the client side.
2026-04-23 10:56:10 +02:00
Christopher Faulet
8247df7c61 REGTESTS: Never reuse server connection in jwt/jws_verify.vtc
A "Connection: close" header is added to responses to avoid any connection
reuse. This should avoid errors on the client side.
2026-04-23 10:56:06 +02:00
Christopher Faulet
2a49386eea BUG/MINOR: stream: Add SF_TXN_HTTP/SF_TXN_PCLI flags in strm_show_flags()
These flags were missing in strm_show_flags(). So let's add them.

No backport needed.
2026-04-23 10:49:32 +02:00
Christopher Faulet
98e1ff7f2c CLEANUP: cli: Fix typos in comments
Some minor typos in comments were fixed.
2026-04-23 10:49:28 +02:00
Christopher Faulet
deba2ffaeb DOC: config: Fix a typo for "external-check" directive
Fix duplicated "to the" in the "external-check" directive description.
2026-04-23 10:49:28 +02:00
Christopher Faulet
e2893dc057 CLEANUP: proxy: Fix typos in comments
Some minor typos in comments were fixed.
2026-04-23 10:49:24 +02:00
Christopher Faulet
cf9694474b BUG/MEDIUM: tcpcheck: Release temporary small chunk when retrying on http-check
When a http request is sent during an http healthcheck, if an error is
triggered while the output buffer is a small buffer, another attempt is made
with a larger one. When this happens, the temporary chunk used to format
headers must be released.

No backport needed.
2026-04-23 10:49:24 +02:00
Christopher Faulet
03da32bbff CLEANUP: http-client: Fix typos in comments
Some minor typos in comments were fixed.
2026-04-23 10:49:21 +02:00
Christopher Faulet
655df2e476 CLEANUP: chunk: Fix a typo in a comment
A minor typo in a comment was fixed.
2026-04-23 10:49:21 +02:00
Christopher Faulet
e4c5862731 CLEANUP: htx: Fix typos in comments
Some minor typos in comments were fixed.
2026-04-23 10:49:17 +02:00
Christopher Faulet
34d6cf6c02 CLEANUP: config: Fix warning about invalid small buffer size
"than" must be used instead of "to".
2026-04-23 10:49:17 +02:00
Christopher Faulet
0fd0f4be44 CLEANUP: haterm: Fix typos in comments
Some minor typos in comments were fixed.
2026-04-23 10:49:13 +02:00
Christopher Faulet
e8aa9a0ae0 BUG/MINOR: tcpcheck: Fix a leak on deinit by releasing ruleset's conf.file
Now healthcheck sections are supported, a ruleset can reference a
configuration file that must be freed on deinit. So let's do so.

No backport needed.
2026-04-23 10:49:13 +02:00
Christopher Faulet
f1540c0575 BUG/MINOR: tcpcheck: Don't release ruleset when parsing 'spop-check' ruleset
Ruleset are stored in a global tree, released on deinit staged. All errors
are fatal and abort the configuration parsing. So the current ruleset must
not be released here.
2026-04-23 10:49:13 +02:00
Christopher Faulet
6ccd962c2d MINOR: tcpcheck: Rely on free_tcpcheck_ruleset() to deinit tcpchecks
There is already a function to release a tcpcheck ruleset. So let's use it
on deinit stage.
2026-04-23 10:49:13 +02:00
Christopher Faulet
862a8c5e7f CLEANUP: tcpcheck: Fix some typos in comments
Some minor typos in comments were fixed.
2026-04-23 10:49:10 +02:00
Christopher Faulet
91f09a0739 BUG/MINOR: http-act: fix a typo in a "del-heeaders-bin" error message
"with is" was replaced by "with" and the action name was not properly
reported (a 's' was missing).

No backport nedded.
2026-04-23 10:49:10 +02:00
Christopher Faulet
7798c38fd3 BUG/MINOR: mux-h1: Fix test to skip trailers from chunked messages
The test to remove trailers from chunked messages was inverted and is thus
ineffective. The flag for the requests was tested on client side and the flag
for the response was tested on server side. It should be the opposite.

This patch must be backported as far as 3.2.
2026-04-23 10:49:10 +02:00
Christopher Faulet
392abee6d4 BUG/MINOR: mux-h1: Fix condition to send null-chunk for bodyless message
When the EOH block is processed, before sending message headers, there is a
test to know if there is no payload. In case of a chunked message, a
null-chunk is emitted, except for bodyless response. For instance, a
response to a HEAD request has no payload at all and no null-chunk.

However, the test for bodyless responses is not correct. Only
H1S_F_BODYLESS_RESP flag is tested. But this flag can be set on server side
when we are processing the request. To fix the issue, the test was
adapted. The null-chunk is added if a message with no payload is chunked and
it is a request or a non-bodyless responses.

This patch must be backported to all stable version.
2026-04-23 10:21:53 +02:00
Willy Tarreau
16485cdebe BUG/MINOR: log: also wait for the response when logging response headers
A typo in commit e51be30f78 ("BUG/MINOR: log: consider format expression
dependencies to decide when to log") made HRSHP appear twice (persistent
response) while the second one ought to be HRSHV (volatile response, e.g.
header values). This is harmless in practice since logs always wait for
at least headers.

This should be backported wherever the patch above was backported.
2026-04-23 08:22:58 +02:00
Olivier Houchard
dca4c379ce BUG/MINOR: H2: Don't forget to free shared_rx_bufs on failure
In h2_init(), if we have a failure while creating the h2c, and we
allocated shared_tx_bufs, don't forget to free it, otherwise we'll have
a memory leak.

This was introduced in 3.1 by commit a891534bfd ("MINOR: mux-h2: allocate
the array of shared rx bufs in the h2c"), so the fix should be backported
as far as 3.2.
2026-04-23 08:12:46 +02:00
Olivier Houchard
0963070d4f BUG/MINOR: h2: Don't look at the exclusive bit for PRIORITY frame
When receiving a PRIORITY frame, when checking if the stream id provided
is ours, ignore bit 31, as it is the exclusive bit, and not part of the
stream id, whoever sends a PRIORITY frame with its own id and the
exclusive bit set will not be considered an error, as it should per the
RFC.

The impact is basically non-existent since we don't use PRIORITY frames,
it's only that we would ignore such an invalid frame instead of breaking
the connection.

The bug was introduced in 1.9 with commit 92153fccd3 ("BUG/MINOR: h2:
properly check PRIORITY frames") so the fix must be backported to all
versions.
2026-04-23 08:09:48 +02:00
Olivier Houchard
915a58c3c1 BUG/MINOR: h2: make tune.h2.log-errors actually work
Commit e67e36c9eb35eb1477ae0e425a660ee0c631cecd introduced
tune.h2.log-errors, that would let you pick if you wanted to know about
stream errors, connection errors, or no error.
However, a logic error made it so no error will be picked for any value
except for "none", in which case connection would be picked. Fix that by
just checking the strcmp() return value correctly.

This should be backported wherever e67e36c9eb35eb1477ae0e425a660ee0c631cecd
has been backported.
2026-04-23 08:04:43 +02:00
Emeric Brun
dbf471f99a BUG/MAJOR: net_helper: ip.fp infinite loop on malformed tcp options
A malformed tcp option with an option length set to 0 can cause
an infinite loop on ip.fp converter.

The patch also forces the computation to use an unsigned char to
avoid a shift back during the parsing.

This fix should be backported on all versions including the ip.fp
converter.
2026-04-22 16:52:30 +02:00