Compare commits

...

331 Commits

Author SHA1 Message Date
Remi Tricot-Le Breton
362ff2628f REGTESTS: jwe: Fix tests of algorithms not supported by AWS-LC
Many tests use the A128KW algorithm which is not supported by AWS-LC but
instead of removing those tests we will just have a hardcoded value set
by default in this case.
2026-01-15 10:56:28 +01:00
Remi Tricot-Le Breton
aba18bac71 MINOR: jwe: Some algorithms not supported by AWS-LC
AWS-LC does not have EVP_aes_128_wrap or EVP_aes_192_wrap so the A128KW
and A192KW algorithms will not be supported for JWE token decryption.
2026-01-15 10:56:28 +01:00
Remi Tricot-Le Breton
39da1845fc DOC: jwe: Add doc for jwt_decrypt converters
Add doc for jwt_decrypt_secret and jwt_decrypt_cert converters.
2026-01-15 10:56:28 +01:00
Remi Tricot-Le Breton
4b73a3ed29 REGTESTS: jwe: Add jwt_decrypt_secret and jwt_decrypt_cert tests
Test the new jwt_decrypt converters.
2026-01-15 10:56:27 +01:00
Remi Tricot-Le Breton
e3a782adb5 MINOR: jwe: Add new jwt_decrypt_cert converter
This converter checks the validity and decrypts the content of a JWE
token that has an asymetric "alg" algorithm (RSA). In such a case, we
must provide a path to an already loaded certificate and private key
that has the "jwt" option set to "on".
2026-01-15 10:56:27 +01:00
Remi Tricot-Le Breton
416b87d5db MINOR: jwe: Add new jwt_decrypt_secret converter
This converter checks the validity and decrypts the content of a JWE
token that has a symetric "alg" algorithm. In such a case, we only
require a secret as parameter in order to decrypt the token.
2026-01-15 10:56:27 +01:00
Remi Tricot-Le Breton
2b45b7bf4f REGTESTS: ssl: Add tests for new aes cbc converters
This test mimics what was already done for the aes_gcm converters. Some
data is encrypted and directly decrypted and we ensure that the output
was not changed.
2026-01-15 10:56:27 +01:00
Remi Tricot-Le Breton
c431034037 MINOR: ssl: Add new aes_cbc_enc/_dec converters
Those converters allow to encrypt or decrypt data with AES in Cipher
Block Chaining mode. They work the same way as the already existing
aes_gcm_enc/_dec ones apart from the AEAD tag notion which is not
supported in CBC mode.
2026-01-15 10:56:27 +01:00
Remi Tricot-Le Breton
f0e64de753 MINOR: ssl: Factorize AES GCM data processing
The parameter parsing and processing and the actual crypto part of the
aes_gcm converter are interleaved. This patch puts the crypto parts in a
dedicated function for better reuse in the upcoming JWE processing.
2026-01-15 10:56:27 +01:00
Amaury Denoyelle
6870551a57 MEDIUM: proxy: force traffic on unpublished/disabled backends
A recent patch has introduced a new state for proxies : unpublished
backends. Such backends won't be eligilible for traffic, thus
use_backend/default_backend rules which target them won't match and
content switching rules processing will continue.

This patch defines a new frontend keywords 'force-be-switch'. This
keyword allows to ignore unpublished or disabled state. Thus,
use_backend/default_backend will match even if the target backend is
unpublished or disabled. This is useful to be able to test a backend
instance before exposing it outside.

This new keyword is converted into a persist rule of new type
PERSIST_TYPE_BE_SWITCH, stored in persist_rules list proxy member. This
is the only persist rule applicable to frontend side. Prior to this
commit, pure frontend proxies persist_rules list were always empty.

This new features requires adjustment in process_switching_rules(). Now,
when a use_backend/default_backend rule matches with an non eligible
backend, frontend persist_rules are inspected to detect if a
force-be-switch is present so that the backend may be selected.
2026-01-15 09:08:19 +01:00
Amaury Denoyelle
16f035d555 MINOR: cfgparse: adapt warnif_cond_conflicts() error output
Utility function warnif_cond_conflicts() is used when parsing an ACL.
Previously, the function directly calls ha_warning() to report an error.
Change the function so that it now takes the error message as argument.
Caller can then output it as wanted.

This change is necessary to use the function when parsing a keyword
registered as cfg_kw_list. The next patch will reuse it.
2026-01-15 09:08:18 +01:00
Amaury Denoyelle
82907d5621 MINOR: stats: report BE unpublished status
A previous patch defines a new proxy status : unpublished backends. This
patch extends this by changing proxy status reported in stats. If
unpublished is set, an extra "(UNPUB)" is added to the field.

Also, HTML stats is also slightly updated. If a backend is up but
unpublished, its status will be reported in orange color.
2026-01-15 09:08:18 +01:00
Amaury Denoyelle
797ec6ede5 MEDIUM: proxy: implement publish/unpublish backend CLI
Define a new set of CLI commands publish/unpublish backend <be>. The
objective is to be able to change the status of a backend to
unpublished. Such a backend is considered ineligible to traffic : this
allows to skip use_backend rules which target it.

Note that contrary to disabled/stopped proxies, an unpublished backend
still has server checks running on it.

Internally, a new proxy flags PR_FL_BE_UNPUBLISHED is defined. CLI
commands handler "publish backend" and "unpublish backend" are executed
under thread isolation. This guarantees that the flag can safely be set
or remove in the CLI handlers, and read during content-switching
processing.
2026-01-15 09:08:18 +01:00
Amaury Denoyelle
21fb0a3f58 MEDIUM: proxy: do not select a backend if disabled
A proxy can be marked as disabled using the keyword with the same name.
The doc mentions that it won't process any traffic. However, this is not
really the case for backends as they may still be selected via switching
rules during stream processing.

In fact, currently access to disabled backends will be conducted up to
assign_server(). However, no eligible server is found at this stage,
resulting in a connection closure or an HTTP 503, which is expected. So
in the end, servers in disabled backends won't receive any traffic. But
this is only because post-parsing steps are not performed on such
backends. Thus, this can be considered as functional but only via
side-effects.

This patch clarifies the handling of disable backends, so that they are
never selected via switching rules. Now, process_switching_rules() will
ignore disable backends and continue rules evaluation.

As this is a behavior change, this patch is labelled as medium. The
documentation manuel for use_backend is updated accordingly.
2026-01-15 09:08:18 +01:00
Amaury Denoyelle
2d26d353ce REGTESTS: add test on backend switching rules selection
Create a new test to ensure that switching rules selection is fine.
Currently, this checks that dynamic backend switching works as expected.
If a matching rule is resolved to an unexisting backend, the default
backend is used instead.

This regtest should be useful as switching-rules will be extended in a
future set of patches to add new abilities on backends, linked to
dynamic backend support.
2026-01-15 09:08:18 +01:00
Amaury Denoyelle
12975c5c37 MEDIUM: stream: refactor switching-rules processing
This commit rewrites process_switching_rules() function. The objective
is to simplify backend selection so that a single unified
stream_set_backend() call is kept, both for regular and default backends
case.

This patch will be useful to add new capabilities on backends, in the
context of dynamic backend support implementation.
2026-01-15 09:08:18 +01:00
Amaury Denoyelle
2f6aab9211 BUG/MINOR: proxy: free persist_rules
force-persist proxy keyword is converted into a persist_rule, stored in
proxy persist_rules list member. Each new rule is dynamically allocated
during parsing.

This commit fixes the memory leak on deinit due to a missing free on
persist_rules list entries. This is done via deinit_proxy()
modification. Each rule in the list is freed, along with its associated
ACL condition type.

This can be backported to every stable version.
2026-01-15 09:08:18 +01:00
Olivier Houchard
a209c35f30 MEDIUM: thread: Turn the group mask in thread set into a group counter
If we want to be able to have more than 64 thread groups, we can no
longer use thread group masks as long.
One remaining place where it is done is in struct thread_set. However,
it is not really used as a mask anywhere, all we want is a thread group
counter, so convert that mask to a counter.
2026-01-15 05:24:53 +01:00
Olivier Houchard
6249698840 BUG/MEDIUM: queues: Fix arithmetic when feeling non_empty_tgids
Fix the arithmetic when pre-filling non_empty_tgids when we still have
more than 32/64 thread groups left, to get the right index, we of course
have to divide the number of thread groups by the number of bits in a
long.
This bug was introduced by commit
7e1fed4b7a8b862bf7722117f002ee91a836beb5, but hopefully was not hit
because it requires to have at least as much thread groups as there are
bits in a long, which is impossible on 64bits machines, as MAX_TGROUPS
is still 32.
2026-01-15 04:28:04 +01:00
Olivier Houchard
1397982599 MINOR: threads: Eliminate all_tgroups_mask.
Now that it is unused, eliminate all_tgroups_mask, as we can't 64bits
masks to represent thread groups, if we want to be able to have more
than 64 thread groups.
2026-01-15 03:46:57 +01:00
Olivier Houchard
7e1fed4b7a MINOR: queues: Turn non_empty_tgids into a long array.
In order to be able to have more than 64 thread groups, turn
non_empty_tgids into a long array, so that we have enough bits to
represent everty thread group, and manipulate it with the ha_bit_*
functions.
2026-01-15 03:46:57 +01:00
Aurelien DARRAGON
2ec387cdc2 BUG/MINOR: http_act: fix deinit performed on uninitialized lf_expr in release_http_map()
As reported by GH user @Lzq-001 on issue #3245, the config below would
cause haproxy to SEGFAULT after having reported an error:

  frontend 0000000
        http-request set-map %[hdr(0000)0_

Root cause is simple, in parse_http_set_map(), we define the release
function (which is responsible to clear lf_expr expressions used by the
action), prior to initializing the expressions, while the release
function assumes the expressions are always initialized.

For all similar actions, we already perform the init prior to setting
the related release function, but this was not the case for
parse_http_set_map(). We fix the bug by initializing the expressions
earlier.

Thanks to @Lzq-001 for having reported the issue and provided a simple
reproducer.

It should be backported to all stable versions, note for versions prior to
3.0, lf_expr_init() should be replace by LIST_INIT(), see
6810c41 ("MEDIUM: tree-wide: add logformat expressions wrapper")
2026-01-14 20:05:39 +01:00
Olivier Houchard
7f4b053b26 MEDIUM: counters: mostly revert da813ae4d7cb77137ed
Contrarily to what was previously believed, there are corner cases where
the counters may not be allocated, and we may want to make them optional
at a later date, so we have to check if those counters are there.
However, just checking that shared.tg is non-NULL is enough, we can then
assume that shared.tg[tgid - 1] has properly been allocated too.
Also modify the various COUNTER_SHARED_* macros to make sure they check
for that too.
2026-01-14 12:39:14 +01:00
Amaury Denoyelle
7aa839296d BUG/MEDIUM: quic: fix ACK ECN frame parsing
ACK frames are either of type 0x02 or 0x03. The latter is an indication
that it contains extra ECN related fields. In haproxy QUIC stack, this
is considered as a different frame type, set to QUIC_FT_ACK_ECN, with
its own set of builder/parser functions.

This patch fixes ACK ECN parsing function. Indeed, the latter suffered
from two issues. First, 'first ACK range' and 'ACK ranges' were
inverted. Then, the three remaining ECN fields were simply ignored by
the parsing function.

This issue can cause desynchronization in the frames parsing code, which
may result in various result. Most of the time, the connection will be
aborted by haproxy due to an invalid frame content read.

Note that this issue was not detected earlier as most clients do not
enable ECN support if the peer is not able to emit ACK ECN frame first,
which haproxy currently never sends. Nevertheless, this is not the case
for every client implementation, thus proper ACK ECN parsing is
mandatory for a proper QUIC stack support.

Fix this by adjusting quic_parse_ack_ecn_frame() function. The remaining
ECN fields are parsed to ensure correct packet parsing. Currently, they
are not used by the congestion controller.

This must be backported up to 2.6.
2026-01-13 15:08:02 +01:00
Olivier Houchard
82196eb74e BUG/MEDIUM: threads: Fix binding thread on bind.
The code to parse the "thread" keyword on bind lines was changed to
check if the thread numbers were correct against the value provided with
max-threads-per-group, if any were provided, however, at the time those
thread keywords have been set, it may not yet have been set, and that
breaks the feature, so revert to check against MAX_THREADS_PER_GROUP instead,
it should have no major impact.
2026-01-13 11:45:46 +01:00
Olivier Houchard
da813ae4d7 MEDIUM: counters: Remove some extra tests
Before updating counters, a few tests are made to check if the counters
exits. but those counters should always exist at this point, so just
remmove them.
This commit should have no impact, but can easily be reverted with no
functional impact if various crashes appear.
2026-01-13 11:12:34 +01:00
Olivier Houchard
5495c88441 MEDIUM: counters: Dynamically allocate per-thread group counters
Instead of statically allocating the per-thread group counters,
based on the max number of thread groups available, allocate
them dynamically, based on the number of thread groups actually
used. That way we can increase the maximum number of thread
groups without using an unreasonable amount of memory.
2026-01-13 11:12:34 +01:00
Willy Tarreau
37057feb80 BUG/MINOR: net_helper: fix IPv6 header length processing
The IPv6 header contains a payload length that excludes the 40 bytes of
IPv6 packet header, which differs from IPv4's total length which includes
it. As a result, the parser was wrong and would only see the IP part and
not the TCP one unless sufficient options were present tocover it.

This issue came in 3.4-dev2 with recent commit e88e03a6e4 ("MINOR:
net_helper: add ip.fp() to build a simplified fingerprint of a SYN"),
so no backport is needed.
2026-01-13 08:42:36 +01:00
Aurelien DARRAGON
fcd4d4a7aa BUG/MINOR: hlua_fcn: ensure Patref:add_bulk() is given a table object before using it
As reported by GH user @kanashimia in GH #3241, providing anything else
than a table to Patref:add_bulk() method could cause a segfault because
we were calling lua_next() with the lua object without ensuring it
actually is a table.

Let's add the missing lua_istable() check on the stack object before
calling lua_next() function on it.

It should be backported up to 3.2 with 884dc62 ("MINOR: hlua_fcn:
add Patref:add_bulk()")
2026-01-12 17:30:54 +01:00
Aurelien DARRAGON
04545cb2b7 BUG/MINOR: hlua_fcn: fix broken yield for Patref:add_bulk()
In GH #3241, GH user @kanashimia reported that the Patref:add_bulk()
method would raise a Lua exception when called with more than 101
elements at once.

As identified by @kanashimia there was an error in the way the
add_bulk() method was forced to yield after 101 elements precisely.
The yield is there to ensure Lua doesn't eat too much ressources at
once and doesn't impact haproxy's core responsiveness, but the check
for the yield was misplaced resulting in improper stack content upon
resume.

Thanks to user @kanashimia who even provided a reproducer which helped
a lot to troubleshoot the issue.

This fix should be backported up to 3.2 with 884dc62 ("MINOR: hlua_fcn:
add Patref:add_bulk()") where the bug was introduced.
2026-01-12 17:30:52 +01:00
Olivier Houchard
b1cfeeef21 BUG/MINOR: stats-file: Use a 16bits variable when loading tgid
Now that the tgid stored in the stats file has been increased to 16bits
by commit 022cb3ab7fdce74de2cf24bea865ecf7015e5754, don't forget to
increase the variable size when reading it from the file, too.
This should have no impact given the maximum thread group limit is still
32.
2026-01-12 09:48:54 +01:00
Olivier Houchard
022cb3ab7f MINOR: stats: Increase the tgid from 8bits to 16bits
Increase the size of the stored tgid in the stat file from 8bits to
32bits, so that we can have more than 256 thread group. 65536 should be
enough for some time.

This bumps thet stat file minor version, as the structure changes.
2026-01-12 09:39:52 +01:00
Olivier Houchard
c0f64fc36a MINOR: receiver: Dynamically alloc the "members" field of shard_info
Instead of always allocating MAX_TGROUPS members, allocate them
dynamically, using the number of thread groups we'll use, so that
increasing MAX_TGROUPS will not have a huge impact on the structure
size.
2026-01-12 09:32:27 +01:00
Tim Duesterhus
96faf71f87 CLEANUP: connection: Remove outdated note about CO_FL 0x00002000 being unused
This flag is used as of commit dcce9369129f6ca9b8eed6b451c0e20c226af2e3
("MINOR: connections: Add a new CO_FL_SSL_NO_CACHED_INFO flag"). This patch
should be backported to 3.3. Apparently dcce9369129 has been backported
to 3.2 and 3.1 already, with that change already applied, so no need for a
backport there.
2026-01-12 03:22:15 +01:00
Willy Tarreau
2560cce7c5 MINOR: tcp-sample: permit retrieving tcp_info from the connection/session stage
The fc_xxx info that are retrieved over tcp_info could currently not
be accessed before a stream is created due to a test that verified the
existence of a stream. The rationale here was that the function works
both for frontend and backend. Let's always retrieve these info from
the session for the frontend case so that it now becomes possible to
set variables at connection/session time. The doc did not mention this
limitation so this could almost be considered as a bug.
2026-01-11 15:48:20 +01:00
Willy Tarreau
880bbeeda4 MINOR: sample: also support retrieving fc.timer.handshake without a stream
Some timers, like the handshake timer, are stored in the session and are
only copied to the logs struct when a stream is created. But this means
we can't measure it without a stream, nor store it once for all in a
variable at session creation time. Let's extend the sample fetch function
to retrieve it from the session when no stream is present. The doc did not
mention this limitation so this could almost be considered as a bug.
2026-01-11 15:48:19 +01:00
Amaury Denoyelle
875bbaa7fc MINOR: cfgparse: remove duplicate "force-persist" in common kw list
"force-persist" proxy keyword is listed twice in common_kw_list. This
patch removes the duplicated occurence.

This could be backported up to 2.4.
2026-01-09 16:45:54 +01:00
Willy Tarreau
46088b7ad0 MEDIUM: config: warn if some userlist hashes are too slow
It was reported in GH #2956 and more recently in GH #3235 that some
hashes are way too slow. The former triggers watchdog warnings during
checks, the second sees the config parsing take 20 seconds. This is
always due to the use of hash algorithms that are not suitable for use
in low-latency environments like web. They might be fine for a local
auth though. The difficulty, as explained by Philipp Hossner, is that
developers are not aware of this cost and adopt this without suspecting
any side effect.

The proposal here is to measure the crypt() call time and emit a warning
if it takes more than 10ms (which is already extreme). This was tested
by Philipp and confirmed to catch his case.

This is marked medium as it might start to report warnings on config
suffering from this problem without ever detecting it till now.
2026-01-09 14:56:18 +01:00
akarl10
a203ce6854 BUG/MINOR: ech/quic: enable ech configuration also for quic listeners
Patch dba4fd24 ("MEDIUM: ssl/ech: config and load keys") introduced
ECH configuration for bind lines, but the QUIC configuration parsers
still suffers from not using the same code as the TCP/TLS one, so the
init for QUIC was missed.

Must be backported in 3.3.
2026-01-08 17:34:28 +01:00
William Lallemand
6e1718ce4b CI: github: remove ERR=1 temporarly from the ECH job
The ECH job still fails to compile since the openssl 4.0 deprecated
functions were not removed yet. Let's remove ERR=1 temporarly.

We do know that there's a regression in OpenSSL 4.0 with these
reg-tests though:

Error: #    top  TEST reg-tests/ssl/set_ssl_crlfile.vtc FAILED (0.219) exit=2
Error: #    top  TEST reg-tests/ssl/set_ssl_cafile.vtc FAILED (0.236) exit=2
Error: #    top  TEST reg-tests/quic/set_ssl_crlfile.vtc FAILED (0.196) exit=2
2026-01-08 17:32:27 +01:00
Christian Ruppert
dbe52cc23e REGTESTS: ssl: Fix reg-tests curve check
OpenSSL changed the output from "Server Temp Key" in prior versions to
"Peer Temp Key" in recent ones.
a39dc27c25
It looks like it affects OpenSSL >=3.5.0
This broke the reg-test for e.g. Debian 13 builds, using OpenSSL 3.5.1

Fixes bug #3238

Could be backported in every branches.

Signed-off-by: Christian Ruppert <idl0r@qasl.de>
2026-01-08 16:14:54 +01:00
William Lallemand
623aa725a2 BUG/MINOR: cli/stick-tables: argument to "show table" is optional
Discussed in issue #3187, the CLI help is confusing for the "show table"
command as it seems that the argument is mandatory.

This patch adds the arguments between square brackets to remove the
confusion.
2026-01-08 11:54:01 +01:00
Willy Tarreau
dbba442740 BUILD: sockpair: fix build issue on macOS related to variable-length arrays
In GH issue #3226, Sergey Fedorov (@barracuda156) reported that since
commit 10c14a1ed0 ("MINOR: proto_sockpair: send_fd_uxst: init iobuf,
cmsghdr, cmsgbuf to zeros"), macOS 10.6.8 with gcc 14.3.0 doesn't build
anymore:

  src/proto_sockpair.c: In function 'send_fd_uxst':
  src/proto_sockpair.c:246:49: error: variable-sized object may not be initialized except with an empty initializer
    246 |         char cmsgbuf[CMSG_SPACE(sizeof(int))] = {0};
        |                                                 ^
  src/proto_sockpair.c:247:45: error: variable-sized object may not be initialized except with an empty initializer
    247 |         char buf[CMSG_SPACE(sizeof(int))] = {0};
        |                                             ^

Upon investigation, it appears that the CMSG_SPACE() macro on this OS
looks too complex for gcc to consider it as a constant, so it takes
these buffers for variable-length arrays and cannot initialize them.

Let's move to a simple memset() instead, which Sergey confirmed fixes
the problem.

This needs to be backported as far as 3.1. Thanks to Sergey for the
report, the bisect and testing the fix.
2026-01-08 09:26:22 +01:00
Hyeonggeun Oh
c17ed69bf3 MINOR: cfgparse: Refactor "userlist" parser to print it in -dKall operation
This patch covers issue https://github.com/haproxy/haproxy/issues/3221.

The parser for the "userlist" section did not use the standard keyword
registration mechanism. Instead, it relied on a series of strcmp()
comparisons to identify keywords such as "group" and "user".

This had two main drawbacks:
1. The keywords were not discoverable by the "-dKall" dump option,
   making it difficult for users to see all available keywords for the
   section.
2. The implementation was inconsistent with the parsers for other
   sections, which have been progressively refactored to use the
   standard cfg_kw_list infrastructure.

This patch refactors the userlist parser to align it with the project's
standard conventions.

The parsing logic for the "group" and "user" keywords has been extracted
from the if/else block in cfg_parse_users() into two new dedicated
functions:
- cfg_parse_users_group()
- cfg_parse_users_user()

These two keywords are now registered via a dedicated cfg_kw_list,
making them visible to the rest of the HAPorxy ecosystem, including the
-dKall dump.
2026-01-07 18:25:09 +01:00
William Lallemand
91cff75908 BUG/MINOR: cfgparse: wrong section name upon error
When a unknown keyword was used in the "userlist" section, the error was
mentioning the "users" section, instead of "userlist".

Could be backported in every branches.
2026-01-07 18:13:12 +01:00
William Lallemand
4aff6d1c25 BUILD: tools: memchr definition changed in C23
New gcc and clang versions from fedora rawhide seems to use the C23
standard by default. This version changes the definition of some
string.h functions, which now return a const char * instead of a char *.

src/tools.c: In function ‘fgets_from_mem’:
src/tools.c:7200:17: warning: assignment discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]
 7200 |         new_pos = memchr(*position, '\n', size);
      |                 ^

Strangely, -Wdiscarded-qualifiers does not seem to catch all the
memchr.

Should fix issue #3228.

This could be backported in previous versions.
2026-01-07 14:51:26 +01:00
William Lallemand
5322bd3785 BUILD: ssl: strchr definition changed in C23
New gcc and clang versions from fedora rawhide seems to use the C23
standard by default. This version changes the definition of some
string.h functions, which now return a const char * instead of a char *.

src/ssl_sock.c: In function ‘SSL_CTX_keylog’:
src/ssl_sock.c:4475:17: error: assignment discards ‘const’ qualifier from pointer target type [-Werror=discarded-qualifiers]
 4475 |         lastarg = strrchr(line, ' ');

Strangely, -Wdiscarded-qualifiers does not seem to catch all the
strrchr.

Should fix issue #3228.

This could be backported in previous versions.
2026-01-07 14:51:26 +01:00
Willy Tarreau
71b00a945d [RELEASE] Released version 3.4-dev2
Released version 3.4-dev2 with the following main changes :
    - BUG/MEDIUM: mworker/listener: ambiguous use of RX_F_INHERITED with shards
    - BUG/MEDIUM: http-ana: Properly detect client abort when forwarding response (v2)
    - BUG/MEDIUM: stconn: Don't report abort from SC if read0 was already received
    - BUG/MEDIUM: quic: Don't try to use hystart if not implemented
    - CLEANUP: backend: Remove useless test on server's xprt
    - CLEANUP: tcpcheck: Remove useless test on the xprt used for healthchecks
    - CLEANUP: ssl-sock: Remove useless tests on connection when resuming TLS session
    - REGTESTS: quic: fix a TLS stack usage
    - REGTESTS: list all skipped tests including 'feature cmd' ones
    - CI: github: remove openssl no-deprecated job
    - CI: github: add a job to test the master branch of OpenSSL
    - CI: github: openssl-master.yml misses actions/checkout
    - BUG/MEDIUM: backend: Do not remove CO_FL_SESS_IDLE in assign_server()
    - CI: github: use git prefix for openssl-master.yml
    - BUG/MEDIUM: mux-h2: synchronize all conditions to create a new backend stream
    - REGTESTS: fix error when no test are skipped
    - MINOR: cpu-topo: Turn the cpu policy configuration into a struct
    - MEDIUM: cpu-topo: Add a "threads-per-core" keyword to cpu-policy
    - MEDIUM: cpu-topo: Add a "cpu-affinity" option
    - MEDIUM: cpu-topo: Add a new "max-threads-per-group" global keyword
    - MEDIUM: cpu-topo: Add the "per-thread" cpu_affinity
    - MEDIUM: cpu-topo: Add the "per-ccx" cpu_affinity
    - BUG/MINOR: cpu-topo: fix -Wlogical-not-parentheses build with clang
    - DOC: config: fix number of values for "cpu-affinity"
    - MINOR: tools: add a secure implementation of memset
    - MINOR: mux-h2: add missing glitch count for non-decodable H2 headers
    - MINOR: mux-h2: perform a graceful close at 75% glitches threshold
    - MEDIUM: mux-h1: implement basic glitches support
    - MINOR: mux-h1: perform a graceful close at 75% glitches threshold
    - MEDIUM: cfgparse: acknowledge that proxy ID auto numbering starts at 2
    - MINOR: cfgparse: remove useless checks on no server in backend
    - OPTIM/MINOR: proxy: do not init proxy management task if unused
    - MINOR: patterns: preliminary changes for reorganization
    - MEDIUM: patterns: reorganize pattern reference elements
    - CLEANUP: patterns: remove dead code
    - OPTIM: patterns: cache the current generation
    - MINOR: tcp: add new bind option "tcp-ss" to instruct the kernel to save the SYN
    - MINOR: protocol: support a generic way to call getsockopt() on a connection
    - MINOR: tcp: implement the get_opt() function
    - MINOR: tcp_sample: implement the fc_saved_syn sample fetch function
    - CLEANUP: assorted typo fixes in the code, commits and doc
    - BUG/MEDIUM: cpu-topo: Don't forget to reset visited_ccx.
    - BUG/MAJOR: set the correct generation ID in pat_ref_append().
    - BUG/MINOR: backend: fix the conn_retries check for TFO
    - BUG/MINOR: backend: inspect request not response buffer to check for TFO
    - MINOR: net_helper: add sample converters to decode ethernet frames
    - MINOR: net_helper: add sample converters to decode IP packet headers
    - MINOR: net_helper: add sample converters to decode TCP headers
    - MINOR: net_helper: add ip.fp() to build a simplified fingerprint of a SYN
    - MINOR: net_helper: prepare the ip.fp() converter to support more options
    - MINOR: net_helper: add an option to ip.fp() to append the TTL to the fingerprint
    - MINOR: net_helper: add an option to ip.fp() to append the source address
    - DOC: config: fix the length attribute name for stick tables of type binary / string
    - MINOR: mworker/cli: only keep positive PIDs in proc_list
    - CLEANUP: mworker: remove duplicate list.h include
    - BUG/MINOR: mworker/cli: fix show proc pagination using reload counter
    - MINOR: mworker/cli: extract worker "show proc" row printer
    - MINOR: cpu-topo: Factorize code
    - MINOR: cpu-topo: Rename variables to better fit their usage
    - BUG/MEDIUM: peers: Properly handle shutdown when trying to get a line
    - BUG/MEDIUM: mux-h1: Take care to update <kop> value during zero-copy forwarding
    - MINOR: threads: Avoid using a thread group mask when stopping.
    - MINOR: hlua: Add support for lua 5.5
    - MEDIUM: cpu-topo: Add an optional directive for per-group affinity
    - BUG/MEDIUM: mworker: can't use signals after a failed reload
    - BUG/MEDIUM: stconn: Move data from <kip> to <kop> during zero-copy forwarding
    - DOC: config: fix a few typos and refine cpu-affinity
    - MINOR: receiver: Remove tgroup_mask from struct shard_info
    - BUG/MINOR: quic: fix deprecated warning for window size keyword
2026-01-07 11:02:12 +01:00
Amaury Denoyelle
e061547d9d BUG/MINOR: quic: fix deprecated warning for window size keyword
QUIC configuration was cleaned up in the previous release. Several
global keyword names were changed to unify the configuration. For each
of them the older keyword is marked as deprecated, with a warning to
mention the newer alternative.

This patch fixes the warning for 'tune.quic.frontend.default-max-size'
as the alternative proposed was not correct. The proper value now is
'tune.quic.fe.cc.max-win-size'.

This must be backported up to 3.3.
2026-01-07 09:54:31 +01:00
Olivier Houchard
41cd589645 MINOR: receiver: Remove tgroup_mask from struct shard_info
The only purpose from tgroup_mask seems to be to calculate how many
tgroups share the same shard, but this is an information we can
calculate differently, we just have to increment the number when a new
receiver is added to the shard, and decrement it when one is detached
from the shard. Removing thread group masks will allow us to increase
the maximum number of thread groups past 64.
2026-01-07 09:27:12 +01:00
Willy Tarreau
c3fcdfaf5c DOC: config: fix a few typos and refine cpu-affinity
There were two typos in the recently updated parts about per-group.
Also, change the commas to ':' after the options values, as sometimes
it would be confusing. Last, place quotes around keyword names so that
they're explicitly referred to as language keywords. No backport is
needed.
2026-01-07 09:19:25 +01:00
Christopher Faulet
83457b9e38 BUG/MEDIUM: stconn: Move data from <kip> to <kop> during zero-copy forwarding
The <kip> of producer was not forwarded to <kop> of consumer when zero-copy
data forwarding was tried. Because of the issue, the chunking of emitted H1
messages could be invalid.

To fix the bug, sc_ep_fwd_kip() must be called at this stage.

This fix is related to the previous one (529a8dbfb "BUG/MEDIUM: mux-h1: Take
care to update <kop> value during zero-copy forwarding"). Both are required
to fully fix the issue #3230.

This patch must be backported to 3.3.
2026-01-06 15:41:50 +01:00
William Lallemand
97490a7789 BUG/MEDIUM: mworker: can't use signals after a failed reload
In issue #3229 it was reported that the master couldn't reload after a
failed reload following a wrong configuration.

It is still possible to do a reload using the "reload" command of the
master CLI. But every signals are blocked.

The problem was introduced in 709cde6d0 ("BUG/MEDIUM: mworker: signals
inconsistencies during startup and reload") which fixes the blocking of
signals during the reload.

However the patch missed a case, indeed, the
run_master_in_recovery_mode() is not being called when the worker failed
to parse the configuration, it is only failing when the master is
failing.

To handle this case, the mworker_unblock_signals() function must be
called upon mworker_on_new_child_failure(). But since this is called in
an haproxy signal handler it would mess with the signals.

Instead, the patch adds a task which is started by the signal handler,
and restores the signals outside of it.

This must be backported as far as 3.1.
2026-01-06 14:27:53 +01:00
Olivier Houchard
56fd0c1a5c MEDIUM: cpu-topo: Add an optional directive for per-group affinity
When using per-group affinity, add an optional new directive. It accepts
the values of "auto", where when multiple thread groups are created, the
available CPUs are split equally across the groups, and is the new
default, and "loose", where all groups are bound to all available CPUs,
this is the old default.
2026-01-06 11:32:45 +01:00
Mike Lothian
1c0f781994 MINOR: hlua: Add support for lua 5.5
Lua 5.5 adds an extra argument to lua_newstate(). Since there are
already a few other ifdefs in hlua.c checking for the Lua version,
and there's a single call place, let's do the same here. This should
be safe for backporting if needed.

Signed-off-by: Mike Lothian <mike@fireburn.co.uk>
2026-01-06 11:05:02 +01:00
Olivier Houchard
853604f87a MINOR: threads: Avoid using a thread group mask when stopping.
Remove the "stopped_tgroup_mask" variable, that indicated which thread
groups were stopping, and instead just use "stopped_tgroups", a counter
indicating how many thread groups are stopping. We want to remove all
thread group masks, so that we can increase the maximum number of thread
groups past 64.
2026-01-06 08:30:55 +01:00
Christopher Faulet
529a8dbfba BUG/MEDIUM: mux-h1: Take care to update <kop> value during zero-copy forwarding
Since the extra field was removed from the HTX structure, a regression was
introduced when forwarding of chunked messages. The <kop> value was not
decreased as it should be when data were sent via the zero-copy
forwarding. Because of this bug, it was possible to announce a chunk size
larger than the chunk data sent.

To fix the bug, an helper function was added to properly update the <kop>
value when a chunk size is emitted. This function is now called when new
chunk is announced, including during zero-copy forwarding.

As a workaround, "tune.disable-zero-copy-forwarding" or just
"tune.h1.zero-copy-fwd-send off" can be set in the global section.

This patch should fix the issue #3230. It must be backported to 3.3.
2026-01-06 07:39:05 +01:00
Christopher Faulet
0b29b76a52 BUG/MEDIUM: peers: Properly handle shutdown when trying to get a line
When a shutdown was reported to a peer applet, the event was not properly
handled if it failed to receive data. The function responsible to get data
was exiting too early if the applet buffer was empty, without testing the
sedesc status. Because of this issue, it was possible to have frozen peer
applets. For instance, it happend on client timeout. With too many frozen
applets, it was possible to reach the maxconn.

This patch should fix the issue #3234. It must be backported to 3.3.
2026-01-05 13:46:57 +01:00
Olivier Houchard
196d16f2b1 MINOR: cpu-topo: Rename variables to better fit their usage
Rename "visited_tsid" and "visited_ccx" to "touse_tsid" and
"touse_ccx". They are not there to remember which tsid/ccx we
alreaday visited, contrarily to visited_ccx_set and
visited_cl_set, they are there to know which tsid/ccx we should
use, so make that clear.
2026-01-05 09:25:48 +01:00
Olivier Houchard
bbf5c30a87 MINOR: cpu-topo: Factorize code
Factorize the code common to cpu_policy_group_by_ccx() and
cpu_policy_group_by_cluster() into a new function,
cpu_policy_assign_threads().
2026-01-05 09:24:44 +01:00
Alexander Stephan
e241144e70 MINOR: mworker/cli: extract worker "show proc" row printer
Introduce cli_append_worker_row() to centralize formatting of a single
worker row. Also, replace duplicated row-printing code in both current
and old workers loops with the helper. Motivation: Reduces LOC and
improves readability by removing duplication.
2026-01-05 08:59:45 +01:00
Alexander Stephan
4c10d9c70c BUG/MINOR: mworker/cli: fix show proc pagination using reload counter
After commit 594408cd612b5 ("BUG/MINOR: mworker/cli: 'show proc' is limited
by buffer size"), related to ticket #3204, the "show proc" logic
has been fixed to be able to print more than 202 processes. However, this
fix can lead to the omission of entries in case they have the same
timestamp.

To fix this, we use the unique reload counter instead of the timestamp.
On partial flush, set ctx->next_reload = child->reloads.
On resume skip entries with child->reloads >= ctx->next_reload.
Finally, we clear ctx->next_reload at the end of a complete dump so
subsequent show proc starts from the top.

Could be backported in all stable branches.
2026-01-05 08:59:34 +01:00
Alexander Stephan
a5f274de92 CLEANUP: mworker: remove duplicate list.h include
Drop the second #include <haproxy/list.h> from mworker.c.
No functional change; reduces redundancy and keeps includes tidy.
2026-01-05 08:59:34 +01:00
Alexander Stephan
c30eeb2967 MINOR: mworker/cli: only keep positive PIDs in proc_list
Change mworker_env_to_proc_list() to if (child->pid > 0) before
LIST_APPEND, avoiding invalid PIDs (0/-1) in the process list.
This has no functional impact beyond stricter validation and it aligns
with existing kill safeguards.
2026-01-05 08:59:14 +01:00
Willy Tarreau
6970c8b8b6 DOC: config: fix the length attribute name for stick tables of type binary / string
The stick-table doc was reworked and moved in 3.2 with commit da67a89f3
("DOC: config: move stick-tables and peers to their own section"), however
the optional length attribute for binary/string types was mistakenly
spelled "length" while it's "len".

This must be backported to 3.2.
2026-01-01 10:52:50 +01:00
Willy Tarreau
a206f85f96 MINOR: net_helper: add an option to ip.fp() to append the source address
The new value 4 will permit to append the source address to the
fingerprint, making it easier to build rules checking a specific path.
2026-01-01 10:32:16 +01:00
Willy Tarreau
70ffae3614 MINOR: net_helper: add an option to ip.fp() to append the TTL to the fingerprint
With mode value 1, the TTL will be appended immediately after the 7 bytes,
making it a 8-byte fingerprint.
2026-01-01 10:19:48 +01:00
Willy Tarreau
2c317cfed7 MINOR: net_helper: prepare the ip.fp() converter to support more options
It can make sense to support extra components in the fingerprint to ease
configuration, so let's change the 0/1 value to a bit field. We also turn
the current 1 (TCP options list) to 2 so that we'll reuse 1 for the TTL.
2026-01-01 10:19:20 +01:00
Willy Tarreau
e88e03a6e4 MINOR: net_helper: add ip.fp() to build a simplified fingerprint of a SYN
Here we collect all the stuff that depends on the sender's settings,
such as TOS, IP version, TTL range, presence of DF bit or IP options,
presence of DATA in the SYN, CWR+ECE flags, TCP header length, wscale,
initial window, mss, as well as the list of TCP extension kinds. It's
obviously fairly limited but can allows to avoid blacklisting certain
valid clients sharing the same IP address as a misbehaving one.

It supports both a short and a long mode depending on the argument.
These can be used with the tcp-ss bind option. The doc was updated
accordingly.
2025-12-31 17:17:38 +01:00
Willy Tarreau
6e46d1345b MINOR: net_helper: add sample converters to decode TCP headers
This adds the following converters, used to decode fields
in an incoming tcp header:

   tcp.dst, tcp.flags, tcp.seq, tcp.src, tcp.win,
   tcp.options.mss, tcp.options.tsopt, tcp.options.tsval,
   tcp.options.wscale, tcp.options_list,

These can be used with the tcp-ss bind option. The doc was updated
accordingly.
2025-12-31 17:17:23 +01:00
Willy Tarreau
e0a7a7ca43 MINOR: net_helper: add sample converters to decode IP packet headers
This adds a few converters that help decode parts of IP packets:
  - ip.data : returns the next header (typically TCP)
  - ip.df   : returns the dont-fragment flags
  - ip.dst  : returns the destination IPv4/v6 address
  - ip.hdr  : returns only the IP header
  - ip.proto: returns the upper level protocol (udp/tcp)
  - ip.src  : returns the source IPv4/v6 address
  - ip.tos  : returns the TOS / TC field
  - ip.ttl  : returns the TTL/HL value
  - ip.ver  : returns the IP version (4 or 6)

These can be used with the tcp-ss bind option. The doc was updated
accordingly.
2025-12-31 17:16:29 +01:00
Willy Tarreau
90d2f157f2 MINOR: net_helper: add sample converters to decode ethernet frames
This adds a few converters that help decode parts of ethernet frame
headers:
  - eth.data : returns the next header (typically IP)
  - eth.dst  : returns the destination MAC address
  - eth.hdr  : returns only the ethernet header
  - eth.proto: returns the ethernet proto
  - eth.src  : returns the source MAC address
  - eth.vlan : returns the VLAN ID when present

These can be used with the tcp-ss bind option. The doc was updated
accordingly.
2025-12-31 17:15:36 +01:00
Willy Tarreau
933cb76461 BUG/MINOR: backend: inspect request not response buffer to check for TFO
In 2.6, do_connect_server() was introduced by commit 0a4dcb65f ("MINOR:
stream-int/backend: Move si_connect() in the backend scope") and changed
the approach to work with a stream instead of a stream-interface. However
si_oc(si) was wrongly turned to &s->res instead of &s->req, which breaks
TFO by always inspecting the response channel to figure whether there are
data pending.

This fix can be backported to all versions till 2.6.
2025-12-31 13:03:53 +01:00
Willy Tarreau
799653d536 BUG/MINOR: backend: fix the conn_retries check for TFO
In 2.6, the retries counter on a stream was changed from retries left
to retries done via commit 731c8e6cf ("MINOR: stream: Simplify retries
counter calculation"). However, one comparison fell through the cracks
in order to detect whether or not we can use TFO (only first attempt),
resulting in TFO never working anymore.

This may be backported to all versions till 2.6.
2025-12-31 13:03:53 +01:00
Maxime Henrion
51592f7a09 BUG/MAJOR: set the correct generation ID in pat_ref_append().
This fixes crashes when creating more than one new revision of a map or
acl file and purging the previous version.
2025-12-31 00:29:47 +01:00
Olivier Houchard
54f59e4669 BUG/MEDIUM: cpu-topo: Don't forget to reset visited_ccx.
We want to reset visited_ccx, as introduced by commit
8aef5bec1ef57eac449298823843d6cc08545745, each time we run the loop,
otherwise the chances of its content being correct are very low, and
will likely end up being bound to the wrong threads.
This was reported in github issue #3224.
2025-12-26 23:55:57 +01:00
Ilia Shipitsin
f8a77ecf62 CLEANUP: assorted typo fixes in the code, commits and doc 2025-12-25 19:45:29 +01:00
Willy Tarreau
6fb521d2f6 MINOR: tcp_sample: implement the fc_saved_syn sample fetch function
This function retrieves the copy of a SYN packet that the system has
kept for us when bind option "tcp-ss" was set to 1 or above. It's
recommended to copy it to a local variable because it will be freed
after being read. It allows to inspect all parts of an incoming SYN
packet, provided that it was preserved (e.g. not possible with SYN
cookies). The doc provides examples of how to use it.
2025-12-24 18:39:37 +01:00
Willy Tarreau
52d60bf9ee MINOR: tcp: implement the get_opt() function
It relies on the generic sock_conn_get_opt() function and will permit
sample fetch functions to retrieve generic TCP-level info.
2025-12-24 18:38:51 +01:00
Willy Tarreau
6d995e59e9 MINOR: protocol: support a generic way to call getsockopt() on a connection
It's regularly needed to call getsockopt() on a connection, but each
time the calling code has to do all the job by itself. This commit adds
a "get_opt()" callback on the protocol struct, that directly calls
getsockopt() on the connection's FD. A generic implementation for
standard sockets is provided, though QUIC would likely require a
different approach, or maybe a mapping. Due to the overlap between
IP/TCP/socket option values, it is necessary for the caller to indicate
both the level and the option. An abstraction of the level could be
done, but the caller would nonetheless have to know the optname, which
is generally defined in the same include files. So for now we'll
consider that this callback is only for very specific use.

The levels and optnames are purposely passed as signed ints so that it
is possible to further extend the API by using negative levels for
internal namespaces.
2025-12-24 18:38:51 +01:00
Willy Tarreau
44c67a08dd MINOR: tcp: add new bind option "tcp-ss" to instruct the kernel to save the SYN
This option enables TCP_SAVE_SYN on the listening socket, which will
cause the kernel to try to save a copy of the SYN packet header (L2,
IP and TCP are supported). This can permit to check the source MAC
address of a client, or find certain TCP options such as a source
address encapsulated using RFC7974. It could also be used as an
alternate approach to retrieving the source and destination addresses
and ports. For now setting the option is enabled, but sample fetch
functions and converters will be needed to extract info.
2025-12-24 11:35:09 +01:00
Maxime Henrion
1fdccbe8da OPTIM: patterns: cache the current generation
This makes a significant difference when loading large files and during
commit and clear operations, thanks to improved cache locality. In the
measurements below, master refers to the code before any of the changes
to the patterns code, not the code before this one commit.

Timing the replacement of 10M entries from the CLI with this command
which also reports timestamps at start, end of upload and end of clear:

  $ (echo "prompt i"; echo "show activity"; echo "prepare acl #0";
     awk '{print "add acl @1 #0",$0}' < bad-ip.map; echo "show activity";
     echo "commit acl @1 #0"; echo "clear acl @0 #0";echo "show activity") |
    socat -t 10 - /tmp/sock1 | grep ^uptim

master, on a 3.7 GHz EPYC, 3 samples:

  uptime_now: 6.087030
  uptime_now: 25.981777  => 21.9 sec insertion time
  uptime_now: 29.286368  => 3.3 sec commit+clear

  uptime_now: 5.748087
  uptime_now: 25.740675  => 20.0s insertion time
  uptime_now: 29.039023  => 3.3 s commit+clear

  uptime_now: 7.065362
  uptime_now: 26.769596  => 19.7s insertion time
  uptime_now: 30.065044  => 3.3s commit+clear

And after this commit:

  uptime_now: 6.119215
  uptime_now: 25.023019  => 18.9 sec insertion time
  uptime_now: 27.155503  => 2.1 sec commit+clear

  uptime_now: 5.675931
  uptime_now: 24.551035  => 18.9s insertion
  uptime_now: 26.652352  => 2.1s commit+clear

  uptime_now: 6.722256
  uptime_now: 25.593952  => 18.9s insertion
  uptime_now: 27.724153  => 2.1s commit+clear

Now timing the startup time with a 10M entries file (on another machine)
on master, 20 samples:

Standard Deviation, s: 0.061652677408033
Mean:        4.217

And after this commit:

Standard Deviation, s: 0.081821371548669
Mean:        3.78
2025-12-23 21:17:39 +01:00
Maxime Henrion
99e625a41d CLEANUP: patterns: remove dead code
Situations where we are iterating over elements and find one with a
different generation ID cannot arise anymore since the elements are kept
per-generation.
2025-12-23 21:17:39 +01:00
Maxime Henrion
545cf59b6f MEDIUM: patterns: reorganize pattern reference elements
Instead of a global list (and tree) of pattern reference elements, we
now have an intermediate pat_ref_gen structure and store the elements in
those. This simplifies the logic of some operations such as commit and
clear, and improves performance in some cases - numbers to be provided
in a subsequent commit after one important optimization is added.

A lot of the changes are due to adding an extra level of indirection,
changing many cases where we iterate over all elements to an outer loop
iterating over the generation and an inner one iterating over the
elements of the current generation. It is therefore easier to read this
patch using 'git diff -w'.
2025-12-23 21:17:39 +01:00
Maxime Henrion
5547bedebb MINOR: patterns: preliminary changes for reorganization
Safe and non-functional changes that only add currently unused
structures, field, functions and macros, in preparation of larger
changes that alter the way pattern reference elements are stored.

This includes code to create and lookup generation objects, and
macros to iterate over the generations of a pattern reference.
2025-12-23 21:17:39 +01:00
Amaury Denoyelle
a4a17eb366 OPTIM/MINOR: proxy: do not init proxy management task if unused
Each proxy has its owned task for internal purpose. Currently, it is
only used either by frontends or if a stick-table is present.

This commit rendres the task allocation optional to only the required
case. Thus, it is not allocated anymore for backend only proxies without
stick-table.
2025-12-23 16:35:49 +01:00
Amaury Denoyelle
c397f6fc9a MINOR: cfgparse: remove useless checks on no server in backend
A legacy check could be activated at compile time to reject backends
without servers. In practice this is not used anymore and does not have
much sense with the introduction of dynamic servers.
2025-12-23 16:35:49 +01:00
Amaury Denoyelle
b562602044 MEDIUM: cfgparse: acknowledge that proxy ID auto numbering starts at 2
Each frontend/backend/listen proxies is assigned an unique ID. It can
either be set explicitely via 'id' keyword, or automatically assigned on
post parsing depending on the available values.

It was expected that the first automatically assigned value would start
at '1'. However, due to a legacy bug this is not the case as this value
is always skipped. Thus, automatically assigned proxies always start at
'2' or more.

To avoid breaking the current existing state, this situation is now
acknowledged with the current patch. The code is rewritten with an
explicit warning to ensure that this won't be fixed without knowing the
current status. A new regtest also ensures this.
2025-12-23 16:35:49 +01:00
Willy Tarreau
5904f8279b MINOR: mux-h1: perform a graceful close at 75% glitches threshold
This avoids hitting the hard wall for connections with non-compliant
peers that are accumulating errors. We recycle the connection early
enough to permit to reset the counter. Example below with a threshold
set to 100:

Before, 1% errors:
  $ h1load -H "Host : blah" -c 1 -n 10000000 0:4445
  #     time conns tot_conn  tot_req      tot_bytes    err  cps  rps  bps   ttfb
           1     1     1039   103872        6763365   1038 1k03 103k 54M1 9.426u
           2     1     2128   212793       14086140   2127 1k08 108k 58M5 8.963u
           3     1     3215   321465       21392137   3214 1k08 108k 58M3 8.982u
           4     1     4307   430684       28735013   4306 1k09 109k 58M6 8.935u
           5     1     5390   538989       36016294   5389 1k08 108k 58M1 9.021u

After, no more errors:
  $ h1load -H "Host : blah" -c 1 -n 10000000 0:4445
  #     time conns tot_conn  tot_req      tot_bytes    err  cps  rps  bps   ttfb
           1     1     1509   113161        7487809      0 1k50 113k 59M9 8.482u
           2     1     3002   225101       15114659      0 1k49 111k 60M9 8.582u
           3     1     4508   338045       22809911      0 1k50 112k 61M5 8.523u
           4     1     5971   447785       30286861      0 1k46 109k 59M7 8.772u
           5     1     7472   560335       37955271      0 1k49 112k 61M2 8.537u
2025-12-20 19:29:37 +01:00
Willy Tarreau
05b457002b MEDIUM: mux-h1: implement basic glitches support
We now count glitches for each parsing error, including those that
have been accepted via accept-unsafe-violations-*. Front and back
are considered and the connection gets killed on error once if the
threshold is reached or passed and the CPU usage is beyond the
configured limit (0 by default). This was tested with:

   curl -ivH "host : blah" 0:4445{,,,,,,,,,}

which sends 10 requests to a configuration having a threshold of 5.
The global keywords are named similarly to H2 and quic:

     tune.h1.be.glitches-threshold xxxx
     tune.h1.fe.glitches-threshold xxxx

The glitches count of each connection is also reported when non-null
in the connection dumps (e.g. "show fd").
2025-12-20 19:29:33 +01:00
Willy Tarreau
0901f60cef MINOR: mux-h2: perform a graceful close at 75% glitches threshold
This avoids hitting the hard wall for connections with non-compliant
peers that would be accumulating errors over long connections. We now
permit to recycle the connection early enough to reset the connection
counter.

This was tested artificially by adding this to h2c_frt_handle_headers():

  h2c_report_glitch(h2c, 1, "new stream");

or this to h2_detach():

  h2c_report_glitch(h2c, 1, "detaching");

and injecting using h2load -c 1 -n 1000 0:4445 on a config featuring
tune.h2.fe.glitches-threshold 1000:

  finished in 8.74ms, 85802.54 req/s, 686.62MB/s
  requests: 1000 total, 751 started, 751 done, 750 succeeded, 250 failed, 250 errored, 0 timeout
  status codes: 750 2xx, 0 3xx, 0 4xx, 0 5xx
  traffic: 6.00MB (6293303) total, 132.57KB (135750) headers (space savings 29.84%), 5.86MB (6144000) data
                       min         max         mean         sd        +/- sd
  time for request:        9us       178us        10us         6us    99.47%
  time for connect:      139us       139us       139us         0us   100.00%
  time to 1st byte:      339us       339us       339us         0us   100.00%
  req/s           :   87477.70    87477.70    87477.70        0.00   100.00%

The failures are due to h2load not supporting reconnection.
2025-12-20 19:26:29 +01:00
Willy Tarreau
52adeef7e1 MINOR: mux-h2: add missing glitch count for non-decodable H2 headers
One rare error case could produce a protocol error on the stream when
not being able to decode response headers wasn't being accounted as a
glitch, so let's fix it.
2025-12-20 19:11:16 +01:00
Maxime Henrion
c8750e4e9d MINOR: tools: add a secure implementation of memset
This guarantees that the compiler will not optimize away the memset()
call if it detects a dead store.

Use this to clear SSL passphrases.

No backport needed.
2025-12-19 17:42:57 +01:00
Willy Tarreau
bd92f34f02 DOC: config: fix number of values for "cpu-affinity"
It said "accepts 2 values" then goes on enumerating 5 since more were
added one at a time. Let's fix it by removing the number. No backport
is needed.
2025-12-19 11:21:09 +01:00
William Lallemand
03340748de BUG/MINOR: cpu-topo: fix -Wlogical-not-parentheses build with clang
src/cpu_topo.c:1325:15: warning: logical not is only applied to the left hand side of this bitwise operator [-Wlogical-not-parentheses]
 1325 |                         } else if (!cpu_policy_conf.flags & CPU_POLICY_ONE_THREAD_PER_CORE)
      |                                    ^                      ~
src/cpu_topo.c:1325:15: note: add parentheses after the '!' to evaluate the bitwise operator first
 1325 |                         } else if (!cpu_policy_conf.flags & CPU_POLICY_ONE_THREAD_PER_CORE)
      |                                    ^
      |                                     (                                                     )
src/cpu_topo.c:1325:15: note: add parentheses around left hand side expression to silence this warning
 1325 |                         } else if (!cpu_policy_conf.flags & CPU_POLICY_ONE_THREAD_PER_CORE)
      |                                    ^
      |                                    (                     )
src/cpu_topo.c:1533:15: warning: logical not is only applied to the left hand side of this bitwise operator [-Wlogical-not-parentheses]
 1533 |                         } else if (!cpu_policy_conf.flags & CPU_POLICY_ONE_THREAD_PER_CORE)
      |                                    ^                      ~
src/cpu_topo.c:1533:15: note: add parentheses after the '!' to evaluate the bitwise operator first
 1533 |                         } else if (!cpu_policy_conf.flags & CPU_POLICY_ONE_THREAD_PER_CORE)
      |                                    ^
      |                                     (                                                     )
src/cpu_topo.c:1533:15: note: add parentheses around left hand side expression to silence this warning
 1533 |                         } else if (!cpu_policy_conf.flags & CPU_POLICY_ONE_THREAD_PER_CORE)
      |                                    ^
      |                                    (                     )

No backport needed.
2025-12-19 10:15:17 +01:00
Olivier Houchard
8aef5bec1e MEDIUM: cpu-topo: Add the "per-ccx" cpu_affinity
Add a new cpu-affinity keyword, "per-ccx".
If used, each thread will be bound to all the hardware threads available
in one CCX of the threads group.
2025-12-18 18:52:52 +01:00
Olivier Houchard
c524b181a2 MEDIUM: cpu-topo: Add the "per-thread" cpu_affinity
Add a new cpu-affinity keyword, "per-thread".
If used, each thread will be bound to only one hardware thread of the
thread group.
If used in conjonction with the "threads-per-core 1" cpu_policy, then
each thread will be bound on a different core.
2025-12-18 18:52:52 +01:00
Olivier Houchard
7e22d9c484 MEDIUM: cpu-topo: Add a new "max-threads-per-group" global keyword
Add a new global keyword, max-threads-per-group. It sets the maximum number of
threads a thread group can contain. Unless the number of thread groups
is fixed with "thread-groups", haproxy will just create more thread
groups as needed.
The default and maximum value is 64.
2025-12-18 18:52:52 +01:00
Olivier Houchard
3865f6c5c6 MEDIUM: cpu-topo: Add a "cpu-affinity" option
Add a new global option, "cpu-affinity", which controls how threads are
bound.
It currently accepts three values, "per-core", which will bind one thread to
each hardware thread of a given core, and "per-group" which will use all
the available hardware threads of the thread group, and "auto", the
default, which will use "per-group", unless "threads-per-core 1" has
been specified in cpu_policy, in which case it will use per-core.
2025-12-18 18:52:52 +01:00
Olivier Houchard
3671652bc9 MEDIUM: cpu-topo: Add a "threads-per-core" keyword to cpu-policy
Add a new, optional key-word to "cpu-policy", "threads-per-core".
It takes one argument, "1" or "auto". If "1" is used, then only one
thread per core will be created, no matter how many hardware thread each
core has. If "auto" is used, then one thread will be created per
hardware thread, as is the case by default.

for example: cpu-policy performance threads-per-core 1
2025-12-18 18:52:52 +01:00
Olivier Houchard
58f04b4615 MINOR: cpu-topo: Turn the cpu policy configuration into a struct
Turn the cpu policy configuration into a struct. Right now it just
contains an int, that represents the policy used, but will get more
information soon.
2025-12-18 18:52:52 +01:00
William Lallemand
876b1e8477 REGTESTS: fix error when no test are skipped
Since commit 1ed2c9d ("REGTESTS: list all skipped tests including
'feature cmd' ones"), the script emits some error when trying to display
the list of skipped tests when there are none.

No backport needed.
2025-12-18 17:26:50 +01:00
Willy Tarreau
9a046fc3ad BUG/MEDIUM: mux-h2: synchronize all conditions to create a new backend stream
In H2 the conditions to create a new stream differ for a client and a
server when a GOAWAY was exchanged. While on the server, any stream
whose ID is lower than or equal to the one advertised in GOAWAY is
valid, for a client it's forbidden to create any stream after receipt
of a GOAWAY, even if its ID is lower than or equal to the last one,
despite the server not being able to tell the difference from the
number of streams in flight.

Unfortunately, the logic in the code did not always reflect this
specificity of the client (the backend code in our case), and most
often considered that it was still permitted to create a new stream
until the max_id was greater than or equal to the advertised last_id.
This is for example what h2c_is_dead() and h2c_streams_left() do. In
other places, such as h2_avail_streams(), the rule is properly taken
into account. Very often the advertised last_id is the same, and this
is also what haproxy does (which explains why it's impossible to
reproduce the issue by chaining two haproxy layers), but a server may
wish to advertise any ID including 2^31-1 as mentioned in the spec,
and in this case the functions would behave differently.

This discrepancy results in a corner case where a GOAWAY received on
an idle connection will cause the next stream creation to be initially
accepted but then rejected via h2_avail_streams(), and the connection
left in a bad state, still attached to the session due to http-reuse
safe, but not reinserted into idle list, since the backend code
currently is not able to properly recover from this situation. Worse,
the idle flags are no longer on it but TASK_F_USR1 still is, and this
makes the recently added BUG_ON() rightfully trigger since this case
is not supposed to happen.

Admittedly more of the backend recovery code needs to be reworked,
however the mux must consistently decide whether or not a connection
may be reused or needs to be released.

This commit fixes the affected logic by introducing a new function
"h2c_reached_last_stream()" which says if a connection has reached its
last stream, regardless of the side, and using this one everywhere
max_id was compared to last_id. This is sufficient to address the
corner case that be_reuse_connection() currently cannot recover from.

This is in relation to GH issue #3215 and it should be sufficient to
fix the issue there. Thanks to Chris Staite for reporting the issue
and kudos to Amaury for spotting the events sequence that can lead
to this situation.

This patch must be backported to 3.3 first, then to older versions
later. It's worth noting that it's much more difficult to observe
the issue before 3.3 because the BUG_ON() is not there, and the
possibly non-released connection might end up being killed for other
reasons (timeouts etc). But one possible visible effect might be the
impossibility to delete a server (which Chris observed in 3.3).
2025-12-18 17:01:32 +01:00
William Lallemand
9c8925ba0d CI: github: use git prefix for openssl-master.yml
Uses the git- prefix in order to get the latest tarball for the master
branch on github.
2025-12-18 16:13:04 +01:00
Olivier Houchard
40d16af7a6 BUG/MEDIUM: backend: Do not remove CO_FL_SESS_IDLE in assign_server()
Back in the mists of time, commit e91a526c8f decided that if we were trying
to stay on the same server than the previous request, and if there were
a connection available in the session, we'd remove its CO_FL_SESS_IDLE.
The reason for doing that has been long lost, probably it fixed a bug at some
point, but it was most probably not the right place to do that. And starting
with 3.3, this triggers a BUG_ON() because that flag is expected later on.
So just revert the commit, if the ancient bug shows up again, it will be
fixed another way.

This should be backported to 3.3. There is little reason to backport it
to previous versions, unless other patches depend on it.
2025-12-18 16:09:34 +01:00
William Lallemand
0c7a4469d2 CI: github: openssl-master.yml misses actions/checkout
The job can't run setup-vtest because the actions/checkout use line is
missing.
2025-12-18 16:03:20 +01:00
William Lallemand
38d3c24931 CI: github: add a job to test the master branch of OpenSSL
vtest.yml only builds the releases of OpenSSL for now, there's no way to
check if we still have issues with the API before a pre-release version
is released.

This job builds the master branch of OpenSSL.

It is run everyday at 3 AM.
2025-12-18 15:43:06 +01:00
William Lallemand
a58f09b63c CI: github: remove openssl no-deprecated job
Remove the openssl no-deprecated job which was used for 1.1.0 API.
It's not useful anymore since it uses the OpenSSL version of the
distributions.

Checking depreciations in the API is still useful when using newest
version of the library. A job for the OpenSSL master branch would be
more useful than that.
2025-12-18 15:22:27 +01:00
William Lallemand
1ed2c9da2c REGTESTS: list all skipped tests including 'feature cmd' ones
The script for running regression tests is modified to improve the
visibility of skipped tests.

Previously, the reasons for skipping tests were only visible during the
test discovery phase when grepping the vtc (REQUIRE, EXCLUDE, etc).
But reg-tests skipped by vtest with the 'feature cmd' keywords were not
listed.

This change introduces the following:
  - vtest does not remove the logs itself anymore, because it is not
    able to let the log available when a test is skipped. So the -L
    parameter is now always passed to vtest
  - All skipped tests during the discovery phase are now logged to a
    'skipped.log' file within the test directory
  - The script now parses vtest logs to find tests that were skipped
    due to missing features (via the 'feature cmd' in .vtc files)
    and adds them to the skipped list.
2025-12-17 15:54:15 +01:00
Frederic Lecaille
8523a5cde0 REGTESTS: quic: fix a TLS stack usage
This issue was reported in GH #3214 where quic/tls13_ssl_crt-list_filters.vtc
QUIC reg test was run without haproxy QUIC support due to OPENSSL_AWSLC enabled
featured.

This is due to the fact that when ssl/tls13_ssl_crt-list_filters.vtc has been
ported to QUIC the feature(OPENSSL) was silly replaced by feature(QUIC) leading
the script to be run even without QUIC support if OR'ed OPENSSL_AWSLC feature is
enabled.

A good method to port these feature() commands to QUIC would have been
to add a feature(QUIC) command seperated from the one used for the supported
TLS stacks identified by the original underlying ssl reg tests (in reg-tests/ssl).
This is what is done by this patch.

Thank you to @idl0r for having reported this issue.
2025-12-15 09:44:42 +01:00
Christopher Faulet
a25394b6c8 CLEANUP: ssl-sock: Remove useless tests on connection when resuming TLS session
In ssl_sock_srv_try_reuse_sess(), the connection is always defined, to TCP
and QUIC connections. No reason to test it. Because it is not so obvious for
the QUIC part, a BUG_ON() could be added here. For now, just remove useless
tests.

This patch should fix a Coverity report from #3213.
2025-12-15 08:16:59 +01:00
Christopher Faulet
d6b1d5f6e9 CLEANUP: tcpcheck: Remove useless test on the xprt used for healthchecks
The xprt used to perform a healthcheck is always defined and cannot be NULL.
So there is no reason to test it. It could lead to wrong assumptions later
in the code.

This patch should fix a Coverity report from #3213.
2025-12-15 08:01:21 +01:00
Christopher Faulet
5c5914c32e CLEANUP: backend: Remove useless test on server's xprt
The server's xprt is always defined and cannot be NULL. So there is no
reason to test it. It could lead to wrong assumptions later in the code.

This patch should fix a Coverity report from #3213.
2025-12-15 07:56:53 +01:00
Olivier Houchard
a08bc468d2 BUG/MEDIUM: quic: Don't try to use hystart if not implemented
Not every CC algos implement hystart, so only call the method if it is
actually there. Failure to do so will cause crashes if hystart is on,
and the algo doesn't implement it.

This should fix github issue #3218

This should be backported up to 3.0.
2025-12-14 16:46:12 +01:00
Christopher Faulet
54e58103e5 BUG/MEDIUM: stconn: Don't report abort from SC if read0 was already received
SC_FL_ABRT_DONE flag should never be set when SC_FL_EOS was already
set. These both flags were introduced to replace the old CF_SHUTR and to
have a flag for shuts driven by the stream and a flag for the read0 received
by the mux. So both flags must not be seen at same time on a SC. It is
espeically important because some processing are performed when these flags
are set. And wrong decisions may be made.

This patch must be backproted as far as 2.8.
2025-12-12 08:41:08 +01:00
Christopher Faulet
a483450fa2 BUG/MEDIUM: http-ana: Properly detect client abort when forwarding response (v2)
The first attempt to fix this issue (c672b2a29 "BUG/MINOR: http-ana:
Properly detect client abort when forwarding the response") was not fully
correct and could be responsible to false report of client abort during the
response forwarding. I guess it is possible to truncate the response.

Instead, we must also take care that the client closed on its side, by
checking SC_FL_EOS flag on the front SC. Indeed, if the client has aborted,
this flag should be set.

This patch should be backported as far as 2.8.
2025-12-12 08:41:08 +01:00
William Lallemand
5b19d95850 BUG/MEDIUM: mworker/listener: ambiguous use of RX_F_INHERITED with shards
The RX_F_INHERITED flag was ambiguous, as it was used to mark both
listeners inherited from the parent process and listeners duplicated
from another local receiver. This could lead to incorrect behavior
concerning socket unbinding and suspension.

This commit refactors the handling of inherited listeners by splitting
the RX_F_INHERITED flag into two more specific flags:

- RX_F_INHERITED_FD: Indicates a listener inherited from the parent
  process via its file descriptor. These listeners should not be unbound
  by the master.

- RX_F_INHERITED_SOCK: Indicates a listener that shares a socket with
  another one, either by being inherited from the parent or by being
  duplicated from another local listener. These listeners should not be
  suspended or resumed individually.

Previously, the sharding code was unconditionally using RX_F_INHERITED
when duplicating a file descriptor. In HAProxy versions prior to 3.1,
this led to a file descriptor leak for duplicated unix stats sockets in
the master process. This would eventually cause the master to crash with
a BUG_ON in fd_insert() once the file descriptor limit was reached.

This must be backported as far as 3.0. Branches earlier than 3.0 are
affected but would need a different patch as the logic is different.
2025-12-11 18:09:47 +01:00
Willy Tarreau
aed953088e [RELEASE] Released version 3.4-dev1
Released version 3.4-dev1 with the following main changes :
    - BUG/MINOR: jwt: Missing "case" in switch statement
    - DOC: configuration: ECH support details
    - Revert "MINOR: quic: use dynamic cc_algo on bind_conf"
    - MINOR: quic: define quic_cc_algo as const
    - MINOR: quic: extract cc-algo parsing in a dedicated function
    - MINOR: quic: implement cc-algo server keyword
    - BUG/MINOR: quic-be: Missing keywords array NULL termination
    - REGTESTS: ssl enable tls12_reuse.vtc for AWS-LC
    - REGTESTS: ssl: split tls*_reuse in stateless and stateful resume tests
    - BUG/MEDIUM: connection: fix "bc_settings_streams_limit" typo
    - BUG/MEDIUM: config: ignore empty args in skipped blocks
    - DOC: config: mention clearer that the cache's total-max-size is mandatory
    - DOC: config: reorder the cache section's keywords
    - BUG/MINOR: quic/ssl: crash in ClientHello callback ssl traces
    - BUG/MINOR: quic-be: handshake errors without connection stream closure
    - MINOR: quic: Add useful debugging traces in qc_idle_timer_do_rearm()
    - REGTESTS: ssl: Move all the SSL certificates, keys, crt-lists inside "certs" directory
    - REGTESTS: quic/ssl: ssl/del_ssl_crt-list.vtc supported by QUIC
    - REGTESTS: quic: dynamic_server_ssl.vtc supported by QUIC
    - REGTESTS: quic: issuers_chain_path.vtc supported by QUIC
    - REGTESTS: quic: new_del_ssl_cafile.vtc supported by QUIC
    - REGTESTS: quic: ocsp_auto_update.vtc supported by QUIC
    - REGTESTS: quic: set_ssl_bug_2265.vtc supported by QUIC
    - MINOR: quic: avoid code duplication in TLS alert callback
    - BUG/MINOR: quic-be: missing connection stream closure upon TLS alert to send
    - REGTESTS: quic: set_ssl_cafile.vtc supported by QUIC
    - REGTESTS: quic: set_ssl_cert_noext.vtc supported by QUIC
    - REGTESTS: quic: set_ssl_cert.vtc supported by QUIC
    - REGTESTS: quic: set_ssl_crlfile.vtc supported by QUIC
    - REGTESTS: quic: set_ssl_server_cert.vtc supported by QUIC
    - REGTESTS: quic: show_ssl_ocspresponse.vtc supported by QUIC
    - REGTESTS: quic: ssl_client_auth.vtc supported by QUIC
    - REGTESTS: quic: ssl_client_samples.vtc supported by QUIC
    - REGTESTS: quic: ssl_default_server.vtc supported by QUIC
    - REGTESTS: quic: new_del_ssl_crlfile.vtc supported by QUIC
    - REGTESTS: quic: ssl_frontend_samples.vtc supported by QUIC
    - REGTESTS: quic: ssl_server_samples.vtc supported by QUIC
    - REGTESTS: quic: ssl_simple_crt-list.vtc supported by QUIC
    - REGTESTS: quic: ssl_sni_auto.vtc code provision for QUIC
    - REGTESTS: quic: ssl_curve_name.vtc supported by QUIC
    - REGTESTS: quic: add_ssl_crt-list.vtc supported by QUIC
    - REGTESTS: add ssl_ciphersuites.vtc (TCP & QUIC)
    - BUG/MINOR: quic: do not set first the default QUIC curves
    - REGTESTS: quic/ssl: Add ssl_curves_selection.vtc
    - BUG/MINOR: ssl: Don't allow to set NULL sni
    - MEDIUM: quic: Add connection as argument when qc_new_conn() is called
    - MINOR: ssl: Add a function to hash SNIs
    - MINOR: ssl: Store hash of the SNI for cached TLS sessions
    - MINOR: ssl: Compare hashes instead of SNIs when a session is cached
    - MINOR: connection/ssl: Store the SNI hash value in the connection itself
    - MEDIUM: tcpcheck/backend: Get the connection SNI before initializing SSL ctx
    - BUG/MEDIUM: ssl: Don't reuse TLS session if the connection's SNI differs
    - MEDIUM: ssl/server: No longer store the SNI of cached TLS sessions
    - BUG/MINOR: log: Dump good %B and %U values in logs
    - BUG/MEDIUM: http-ana: Don't close server connection on read0 in TUNNEL mode
    - DOC: config: Fix description of the spop mode
    - DOC: config: Improve spop mode documentation
    - MINOR: ssl: Split ssl_crt-list_filters.vtc in two files by TLS version
    - REGTESTS: quic: tls13_ssl_crt-list_filters.vtc supported by QUIC
    - BUG/MEDIUM: h3: do not access QCS <sd> if not allocated
    - CLEANUP: mworker/cli: remove useless variable
    - BUG/MINOR: mworker/cli: 'show proc' is limited by buffer size
    - BUG/MEDIUM: ssl: Always check the ALPN after handshake
    - MINOR: connections: Add a new CO_FL_SSL_NO_CACHED_INFO flag
    - BUG/MEDIUM: ssl: Don't store the ALPN for check connections
    - BUG/MEDIUM: ssl: Don't resume session for check connections
    - CLEANUP: improvements to the alignment macros
    - CLEANUP: use the automatic alignment feature
    - CLEANUP: more conversions and cleanups for alignment
    - BUG/MEDIUM: h3: fix access to QCS <sd> definitely
    - MINOR: h2/trace: emit a trace of the received RST_STREAM type
2025-12-10 16:52:30 +01:00
Willy Tarreau
3ec5818807 MINOR: h2/trace: emit a trace of the received RST_STREAM type
Right now we don't get any state trace when receiving an RST_STREAM, and
this is not convenient because RST_STREAM(0) is not visible at all, except
in developer level because the function is entered and left.

Let's extract the RST code first and always log it using TRACE_PRINTF()
(along with h2c/h2s) so that it's possible to detect certain codes being
used.
2025-12-10 15:58:56 +01:00
Amaury Denoyelle
5b8e6d6811 BUG/MEDIUM: h3: fix access to QCS <sd> definitely
The previous patch tried to fix access to QCS <sd> member, as the latter
is not always allocated anymore on the frontend side.

  a15f0461a016a664427f5aaad2227adcc622c882
  BUG/MEDIUM: h3: do not access QCS <sd> if not allocated

In particular, access was prevented after HEADERS parsing in case
h3_req_headers_to_htx() returned an error, which indicates that the
stream-endpoint allocation was not performed. However, this still is not
enough when QCS instance is already closed at this step. Indeed, in this
case, h3_req_headers_to_htx() returns OK but stream-endpoint allocation
is skipped as an optimization as no data exchange will be performed.

To definitely fix this kind of problems, add checks on qcs <sd> member
before accessing it in H3 layer. This method is the safest one to ensure
there is no NULL dereferencement.

This should fix github issue #3211.

This must be backported along the above mentionned patch.
2025-12-10 12:04:37 +01:00
Maxime Henrion
6eedd0d485 CLEANUP: more conversions and cleanups for alignment
- Convert additional cases to use the automatic alignment feature for
  the THREAD_ALIGN(ED) macros. This includes some cases that are less
  obviously correct where it seems we wanted to align only in the
  USE_THREAD case but were not using the thread specific macros.
- Also move some alignment requirements to the structure definition
  instead of having it on variable declaration.
2025-12-09 17:40:58 +01:00
Maxime Henrion
bc8e14ec23 CLEANUP: use the automatic alignment feature
- Use the automatic alignment feature instead of hardcoding 64 all over
  the code.
- This also converts a few bare __attribute__((aligned(X))) to using the
  ALIGNED macro.
2025-12-09 17:14:58 +01:00
Maxime Henrion
74719dc457 CLEANUP: improvements to the alignment macros
- It is now possible to use the THREAD_ALIGN and THREAD_ALIGNED macros
  without a parameter. In this case, we automatically align on the cache
  line size.
- The cache line size is set to 64 by default to match the current code,
  but it can be overridden on the command line.
- This required moving the DEFVAL/DEFNULL/DEFZERO macros to compiler.h
  instead of tools-t.h, to avoid namespace pollution if we included
  tools-t.h from compiler.h.
2025-12-09 17:05:52 +01:00
Olivier Houchard
420b42df1c BUG/MEDIUM: ssl: Don't resume session for check connections
Don't attempt to use stored sessions when creating new check
connections, as the check SSL parameters might be different from the
server's ones.
This has not been proven to be a problem yet, but it doesn't mean it
can't be, and this should be backported up to 2.8 along with
dcce9369129f6ca9b8eed6b451c0e20c226af2e3 if it is.
2025-12-09 16:45:54 +01:00
Olivier Houchard
be4e1220c2 BUG/MEDIUM: ssl: Don't store the ALPN for check connections
When establishing check connections, do not store the negociated ALPN
into the server's path_param if the connection is a check connection, as
it may use different SSL parameters than the regular connections. To do
so, only store them if the CO_FL_SSL_NO_CACHED_INFO is not set.
Otherwise, the check ALPN may be stored, and the wrong mux can be used
for regular connections, which will end up generating 502s.

This should fix Github issue #3207

This should be backported to 3.3.
2025-12-09 16:43:31 +01:00
Olivier Houchard
dcce936912 MINOR: connections: Add a new CO_FL_SSL_NO_CACHED_INFO flag
Add a new flag to connections, CO_FL_SSL_NO_CACHED_INFO, and set it for
checks.
It lets the ssl layer know that he should not use cached informations,
such as the ALPN as stored in the server, or cached sessions.
This wlil be used for checks, as checks may target different servers, or
used a different SSL configuration, so we can't assume the stored
informations are correct.

This should be backported to 3.3, and may be backported up to 2.8 if the
attempts to do session resume by checks is proven to be a problem.
2025-12-09 16:43:31 +01:00
Olivier Houchard
260d64d787 BUG/MEDIUM: ssl: Always check the ALPN after handshake
Move the code that is responsible for checking the ALPN, and updating
the one stored in the server's path_param, from after we created the
mux, to after we did an handshake. Once we did it once, the mux will not
be created by the ssl code anymore, as when we know which mux to use
thanks to the ALPN, it will be done earlier in connect_server(), so in
the unlikely event it changes, we would not detect it anymore, and we'd
keep on creating the wrong mux.
This can be reproduced by doing a first request, and then changing the
ALPN of the server without haproxy noticing (ie without haproxy noticing
that the server went down).

This should be backported to 3.3.
2025-12-09 16:43:31 +01:00
William Lallemand
594408cd61 BUG/MINOR: mworker/cli: 'show proc' is limited by buffer size
In ticket #3204, it was reported that "show proc" is not able to display
more than 202 processes. Indeed the bufsize is 16k by default in the
master, and can't be changed anymore since 3.1.

This patch allows the 'show proc' to start again to dump when the buffer
is full, based on the timestamp of the last PID it attempted to dump.
Using pointers or count the number of processes might not be a good idea
since the list can change between calls.

Could be backported in all stable branche.
2025-12-09 16:09:10 +01:00
William Lallemand
dabe8856ad CLEANUP: mworker/cli: remove useless variable
The msg variable is declared and free but never used, this patch removes it.
2025-12-09 16:09:10 +01:00
Amaury Denoyelle
a15f0461a0 BUG/MEDIUM: h3: do not access QCS <sd> if not allocated
Since the following commit, allocation of QCS stream-endpoint on FE side
has been delayed. The objective is to allocate it only for QCS attached
to an upper stream object. Stream-endpoint allocation is now performed
on qcs_attach_sc() called during HEADERS parsing.

  commit e6064c561684d9b079e3b5725d38dc3b5c1b5cd5
  OPTIM: mux-quic: delay FE sedesc alloc to stream creation

Also, stream-endpoint is accessed through the QCS instance after HEADERS
or DATA frames parsing, to update the known input payload length. The
above patch triggered regressions as in some code paths, <sd> field is
dereferenced while still being NULL.

This patch fixes this by restricting access to <sd> field after newer
conditions.

First, after HEADERS parsing, known input length is only updated if
h3_req_headers_to_htx() previously returned a success value, which
guarantee that qcs_attach_sc() has been executed.

After DATA parsing, <sd> is only accessed after the frame validity
check. This ensures that HEADERS were already parsed, thus guaranteing
that stream-endpoint is allocated.

This should fix github issue #3211.

This must be backported up to 3.3. This is sufficient, unless above
patch is backported to previous releases, in which case the current one
must be picked with it.
2025-12-09 15:00:23 +01:00
Frederic Lecaille
18625f7ff3 REGTESTS: quic: tls13_ssl_crt-list_filters.vtc supported by QUIC
ssl/tls13_ssl_crt-list_filters.vtc was renamed to ssl/tls13_ssl_crt-list_filters.vtci
to produce a common part runnable both for QUIC and TCP listeners.
Then tls13_ssl_crt-list_filters.vtc files were created both under ssl and quic directories
to call this .vtci file with correct VTC_SOCK_TYPE environment values
("quic" for QUIC listeners and "stream" for TCP listeners);
2025-12-09 07:42:45 +01:00
Frederic Lecaille
c005ed0df8 MINOR: ssl: Split ssl_crt-list_filters.vtc in two files by TLS version
Seperate the section from ssl_crt-list_filters.vtc which supports TLS 1.2 and 1.3
versions to produce tls12_ssl_crt-list_filters.vtc and tls13_ssl_crt-list_filters.vtc.
2025-12-09 07:42:45 +01:00
Christopher Faulet
2fa3b4c3a3 DOC: config: Improve spop mode documentation
The spop mode description was a bit confusing. So let's improve it.

Thanks to @NickMRamirez.

This patch shoud fix issue #3206. It could be backported as far as 3.1.
2025-12-08 15:24:05 +01:00
Christopher Faulet
e16dcab92f DOC: config: Fix description of the spop mode
It was mentionned that the spop mode turned the backend into a "log"
backend. It is obviously wrong. It turns the backend into a spop backend.

This patch should be backported as far as 3.1.
2025-12-08 15:22:01 +01:00
Christopher Faulet
3cf4e7afb9 BUG/MEDIUM: http-ana: Don't close server connection on read0 in TUNNEL mode
It is a very old bug (2012), dating from the introduction of the keep-alive
support to HAProxy. When a request is fully received, the SC on backend side
is switched to NOHALF mode. It means that when the read0 is received from
the server, the server connection is immediately closed. It is expected to
do so at the end of a classical request. However, it must not be performed
if the session is switched to the TUNNEL mode (after an HTTP/1 upgrade or a
CONNECT). The client may still have data to send to the server. And closing
brutally the server connection this way will be handled as an error on
client side.

This bug is especially visible when a H2 connection on client side because a
RST_STREAM is emitted and a "SD--" is reported in logs.

Thanks to @chrisstaite

This patch should fix the issue #3205. It must be backported to all stable
versions.
2025-12-08 15:22:01 +01:00
Christopher Faulet
5d74980277 BUG/MINOR: log: Dump good %B and %U values in logs
When per-stream "bytes_in" and "bytes_out" counters where replaced in 3.3,
the wrong counters were used for %B and %U values in logs. In the
configuration manual and the commit message, it was specificed that
"bytes_in" was replaced by "req_in" and "bytes_out" by "res_in", but in the
code, wrong counters were used. It is now fixed.

This patch should fix the issue #3208. It must be backported to 3.3.
2025-12-08 15:22:01 +01:00
Christopher Faulet
be998b590e MEDIUM: ssl/server: No longer store the SNI of cached TLS sessions
Thanks to the previous patch, "BUG/MEDIUM: ssl: Don't reuse TLS session
if the connection's SNI differs", it is no useless to store the SNI of
cached TLS sessions. This SNI is no longer tested and new connections
reusing a session must have the same SNI.

The main change here is for the ssl_sock_set_servername() function. It is no
longer possible to compare the SNI of the reused session with the one of the
new connection. So, the SNI is always set, with no other processing. Mainly,
the session is not destroyed when SNIs don't match. It means the commit
119a4084bf ("BUG/MEDIUM: ssl: for a handshake when server-side SNI changes")
is implicitly reverted.

It is good to note that it is unclear for me when and why the reused session
should be destroyed. Because I'm unable to reproduce any issue fixed by the
commit above.

This patch could be backported as far as 3.0 with the commit above.
2025-12-08 15:22:01 +01:00
Christopher Faulet
5702009c8c BUG/MEDIUM: ssl: Don't reuse TLS session if the connection's SNI differs
When a new SSL server connection is created, if no SNI is set, it is
possible to inherit from the one of the reused TLS session. The bug was
introduced by the commit 95ac5fe4a ("MEDIUM: ssl_sock: always use the SSL's
server name, not the one from the tid"). The mixup is possible between
regular connections but also with health-checks connections.

But it is only the visible part of the bug. If the SNI of the cached TLS
session does not match the one of the new connection, no reuse must be
performed at all.

To fix the bug, hash of the SNI of the reused session is compared with the
one of the new connection. The TLS session is reused only if the hashes are
the same.

This patch should fix the issue #3195. It must be slowly backported as far
as 3.0. it relies on the following series:

  * MEDIUM: tcpcheck/backend: Get the connection SNI before initializing SSL ctx
  * MINOR: connection/ssl: Store the SNI hash value in the connection itself
  * MEDIUM: ssl: Store hash of the SNI for cached TLS sessions
  * MINOR: ssl: Add a function to hash SNIs
  * MEDIUM: quic: Add connection as argument when qc_new_conn() is called
  * BUG/MINOR: ssl: Don't allow to set NULL sni
2025-12-08 15:22:01 +01:00
Christopher Faulet
7e9d921141 MEDIUM: tcpcheck/backend: Get the connection SNI before initializing SSL ctx
The SNI of a new connection is now retrieved earlier, before the
initialization of the SSL context. So, concretely, it is now performed
before calling conn_prepare(). The SNI is then set just after.
2025-12-08 15:22:01 +01:00
Christopher Faulet
28654f3c9b MINOR: connection/ssl: Store the SNI hash value in the connection itself
When a SNI is set on a new connection, its hash is now saved in the
connection itself. To do so, a dedicated field was added into the connection
strucutre, called sni_hash. For now, this value is only used when the TLS
session is cached.
2025-12-08 15:22:01 +01:00
Christopher Faulet
92f77cb3e6 MINOR: ssl: Compare hashes instead of SNIs when a session is cached
This patch relies on the commit "MINOR: ssl: Store hash of the SNI for
cached TLS sessions". We now use the hash of the SNIs instead of the SNIs
themselves to know if we must update the cached SNI or not.
2025-12-08 15:22:01 +01:00
Christopher Faulet
9794585204 MINOR: ssl: Store hash of the SNI for cached TLS sessions
For cached TLS sessions, in addition to the SNI itself, its hash is now also
saved. No changes are expected here because this hash is not used for now.

This commit relies on:

  * MINOR: ssl: Add a function to hash SNIs
2025-12-08 15:22:00 +01:00
Christopher Faulet
d993e1eeae MINOR: ssl: Add a function to hash SNIs
This patch only adds the function ssl_sock_sni_hash() that can be used to
get the hash value corresponding to an SNI. A global seed, sni_hash_seed, is
used.
2025-12-08 15:22:00 +01:00
Christopher Faulet
a83ed86b78 MEDIUM: quic: Add connection as argument when qc_new_conn() is called
This patch reverts the commit efe60745b ("MINOR: quic: remove connection arg
from qc_new_conn()"). The connection will be mandatory when the QUIC
connection is created on backend side to fix an issue when we try to reuse a
TLS session.

So, the connection is again an argument of qc_new_conn(), the 4th
argument. It is NULL for frontend QUIC connections but there is no special
check on it.
2025-12-08 15:22:00 +01:00
Christopher Faulet
3534efe798 BUG/MINOR: ssl: Don't allow to set NULL sni
ssl_sock_set_servername() function was documented to support NULL sni to
unset it. However, the man page of SSL_get_servername() does not mentionned
it is supported or not. And it is in fact not supported by WolfSSL and leads
to a crash if we do so.

For now, this function is never called with a NULL sni, so it better and
safer to forbid this case. Now, if the sni is NULL, the function does
nothing.

This patch could be backported to all stable versions.
2025-12-08 15:22:00 +01:00
Frederic Lecaille
7872260525 REGTESTS: quic/ssl: Add ssl_curves_selection.vtc
This reg test ensures the curves may be correctly set for frontend
and backends by "ssl-default-bind-curves" and "ssl-default-server-curves"
as global options or with "curves" options on "bind" and "server" lines.
2025-12-08 10:40:59 +01:00
Frederic Lecaille
90064ac88b BUG/MINOR: quic: do not set first the default QUIC curves
This patch impacts both the QUIC frontends and listeners.

Note that "ssl-default-bind-ciphersuites", "ssl-default-bind-curves",
are not ignored by QUIC by the frontend. This is also the case for the
backends with "ssl-default-server-ciphersuites" and "ssl-default-server-curves".

These settings are set by ssl_sock_prepare_ctx() for the frontends and
by ssl_sock_prepare_srv_ssl_ctx() for the backends. But ssl_quic_initial_ctx()
first sets the default QUIC frontends (see <quic_ciphers> and <quic_groups>)
before these ssl_sock.c function are called, leading some TLS stack to
refuse them if they do not support them. This is the case for some OpenSSL 3.5
stack with FIPS support. They do not support X25519.

To fix this, set the default QUIC ciphersuites and curves only if not already
set by the settings mentioned above.

Rename <quic_ciphers> global variable to <default_quic_ciphersuites>
and <quic_groups> to <default_quic_curves> to reflect the OpenSSL API naming.

These options are taken into an account by ssl_quic_initial_ctx()
which inspects these four variable before calling SSL_CTX_set_ciphersuites()
with <default_quic_ciphersuites> as parameter and SSL_CTX_set_curves() with
<default_quic_curves> as parameter if needed, that is to say, if no ciphersuites
and curves were set by "ssl-default-bind-ciphersuites", "ssl-default-bind-curves"
as global options  or "ciphersuites", "curves" as "bind" line options.
Note that the bind_conf struct is not modified when no "ciphersuites" or
"curves" option are used on "bind" lines.

On backend side, rely on ssl_sock_init_srv() to set the server ciphersuites
and curves. This function is modified to use respectively <default_quic_ciphersuites>
and <default_quic_curves> if no ciphersuites  and curves were set by
"ssl-default-server-ciphersuites", "ssl-default-server-curves" as global options
or "ciphersuites", "curves" as "server" line options.

Thank to @rwagoner for having reported this issue in GH #3194 when using
an OpenSSL 3.5.4 stack with FIPS support.

Must be backported as far as 2.6
2025-12-08 10:40:59 +01:00
Frederic Lecaille
a2d2cda631 REGTESTS: add ssl_ciphersuites.vtc (TCP & QUIC)
This reg test ensures the ciphersuites may be correctly set for frontend
and backends by "ssl-default-bind-ciphersuites" and "ssl-default-server-ciphersuites"
as global options or with "ciphersuites" options on "bind" and "server" lines.
2025-12-08 10:40:59 +01:00
Frederic Lecaille
062a0ed899 REGTESTS: quic: add_ssl_crt-list.vtc supported by QUIC
ssl/add_ssl_crt-list.vtc was renamed to ssl/add_ssl_crt-list.vtci
to produce a common part runnable both for QUIC and TCP listeners.
Then add_ssl_crt-list.vtc files were created both under ssl and quic directories
to call this .vtci file with correct VTC_SOCK_TYPE environment values
("quic" for QUIC listeners and "stream" for TCP listeners);
2025-12-08 10:40:59 +01:00
Frederic Lecaille
4214c97dd4 REGTESTS: quic: ssl_curve_name.vtc supported by QUIC
ssl/ssl_curve_name.vtc was renamed to ssl/ssl_curve_name.vtci
to produce a common part runnable both for QUIC and TCP listeners.
Then ssl_curve_name.vtc files were created both under ssl and quic directories
to call this .vtci file with correct VTC_SOCK_TYPE environment values
("quic" for QUIC listeners and "stream" for TCP listeners);

Note that this script works by chance for QUIC because the curves
selection matches the default ones used by QUIC.
2025-12-08 10:40:59 +01:00
Frederic Lecaille
c615b14fac REGTESTS: quic: ssl_sni_auto.vtc code provision for QUIC
ssl/ssl_sni_auto.vtc was renamed to ssl/ssl_sni_auto.vtci
to produce a common part runnable both for QUIC and TCP listeners.
Then ssl_sni_auto.vtc files were created both under ssl and quic directories
to call this .vtci file with correct VTC_SOCK_TYPE environment values
("quic" for QUIC listeners and "stream" for TCP listeners);

Mark the test as broken for QUIC
2025-12-08 10:40:59 +01:00
Frederic Lecaille
7bb7b26317 REGTESTS: quic: ssl_simple_crt-list.vtc supported by QUIC
ssl/ssl_simple_crt-list.vtc was renamed to ssl/ssl_simple_crt-list.vtci
to produce a common part runnable both for QUIC and TCP listeners.
Then ssl_simple_crt-list.vtc files were created both under ssl and quic directories
to call this .vtci file with correct VTC_SOCK_TYPE environment values
("quic" for QUIC listeners and "stream" for TCP listeners);
2025-12-08 10:40:59 +01:00
Frederic Lecaille
b87bee8e04 REGTESTS: quic: ssl_server_samples.vtc supported by QUIC
ssl/ssl_server_samples.vtc was renamed to ssl/ssl_server_samples.vtci
to produce a common part runnable both for QUIC and TCP listeners.
Then ssl_server_samples.vtc files were created both under ssl and quic directories
to call this .vtci file with correct VTC_SOCK_TYPE environment values
("quic" for QUIC listeners and "stream" for TCP listeners);
2025-12-08 10:40:59 +01:00
Frederic Lecaille
25529dddb6 REGTESTS: quic: ssl_frontend_samples.vtc supported by QUIC
ssl/ssl_frontend_samples.vtc was renamed to ssl/ssl_frontend_samples.vtci
to produce a common part runnable both for QUIC and TCP listeners.
Then ssl_frontend_samples.vtc files were created both under ssl and quic directories
to call this .vtci file with correct VTC_SOCK_TYPE environment values
("quic" for QUIC listeners and "stream" for TCP listeners);
2025-12-08 10:40:59 +01:00
Frederic Lecaille
5cf5f76a90 REGTESTS: quic: new_del_ssl_crlfile.vtc supported by QUIC
ssl/new_del_ssl_crlfile.vtc was renamed to ssl/new_del_ssl_crlfile.vtci
to produce a common part runnable both for QUIC and TCP listeners.
Then new_del_ssl_crlfile.vtc files were created both under ssl and quic directories
to call this .vtci file with correct VTC_SOCK_TYPE environment values
("quic" for QUIC listeners and "stream" for TCP listeners);
2025-12-08 10:40:59 +01:00
Frederic Lecaille
fc0c52f2af REGTESTS: quic: ssl_default_server.vtc supported by QUIC
ssl/ssl_default_server.vtc was renamed to ssl/ssl_default_server.vtci
to produce a common part runnable both for QUIC and TCP listeners.
Then ssl_default_server.vtc files were created both under ssl and quic directories
to call this .vtci file with correct VTC_SOCK_TYPE environment values
("quic" for QUIC listeners and "stream" for TCP listeners);
2025-12-08 10:40:59 +01:00
Frederic Lecaille
4bff826204 REGTESTS: quic: ssl_client_samples.vtc supported by QUIC
ssl/ssl_client_samples.vtc was renamed to ssl/ssl_client_samples.vtci
to produce a common part runnable both for QUIC and TCP listeners.
Then ssl_client_samples.vtc files were created both under ssl and quic directories
to call this .vtci file with correct VTC_SOCK_TYPE environment values
("quic" for QUIC listeners and "stream" for TCP listeners);
2025-12-08 10:40:59 +01:00
Frederic Lecaille
47889154d2 REGTESTS: quic: ssl_client_auth.vtc supported by QUIC
ssl/ssl_client_auth.vtc was renamed to ssl/ssl_client_auth.vtci
to produce a common part runnable both for QUIC and TCP listeners.
Then ssl_client_auth.vtc files were created both under ssl and quic directories
to call this .vtci file with correct VTC_SOCK_TYPE environment values
("quic" for QUIC listeners and "stream" for TCP listeners);
2025-12-08 10:40:59 +01:00
Frederic Lecaille
b285f11cd6 REGTESTS: quic: show_ssl_ocspresponse.vtc supported by QUIC
ssl/show_ssl_ocspresponse.vtc was renamed to ssl/show_ssl_ocspresponse.vtci
to produce a common part runnable both for QUIC and TCP listeners.
Then show_ssl_ocspresponse.vtc files were created both under ssl and quic directories
to call this .vtci file with correct VTC_SOCK_TYPE environment values
("quic" for QUIC listeners and "stream" for TCP listeners);
2025-12-08 10:40:59 +01:00
Frederic Lecaille
c4d066e735 REGTESTS: quic: set_ssl_server_cert.vtc supported by QUIC
ssl/set_ssl_server_cert.vtc was renamed to ssl/set_ssl_server_cert.vtci
to produce a common part runnable both for QUIC and TCP listeners.
Then set_ssl_server_cert.vtc files were created both under ssl and quic directories
to call this .vtci file with correct VTC_SOCK_TYPE environment values
("quic" for QUIC listeners and "stream" for TCP listeners);
2025-12-08 10:40:59 +01:00
Frederic Lecaille
c1a818c204 REGTESTS: quic: set_ssl_crlfile.vtc supported by QUIC
ssl/set_ssl_crlfile.vtc was renamed to ssl/set_ssl_crlfile.vtci
to produce a common part runnable both for QUIC and TCP listeners.
Then set_ssl_crlfile.vtc files were created both under ssl and quic directories
to call this .vtci file with correct VTC_SOCK_TYPE environment values
("quic" for QUIC listeners and "stream" for TCP listeners);
2025-12-08 10:40:59 +01:00
Frederic Lecaille
83b3e2876e REGTESTS: quic: set_ssl_cert.vtc supported by QUIC
ssl/set_ssl_cert.vtc was renamed to ssl/set_ssl_cert.vtci
to produce a common part runnable both for QUIC and TCP listeners.
Then set_ssl_cert.vtc files were created both under ssl and quic directories
to call this .vtci file with correct VTC_SOCK_TYPE environment values
("quic" for QUIC listeners and "stream" for TCP listeners);
2025-12-08 10:40:59 +01:00
Frederic Lecaille
cb1e9e3cd8 REGTESTS: quic: set_ssl_cert_noext.vtc supported by QUIC
ssl/set_ssl_cert_noext.vtc was renamed to ssl/set_ssl_cert_noext.vtci
to produce a common part runnable both for QUIC and TCP listeners.
Then set_ssl_cert_noext.vtc files were created both under ssl and quic directories
to call this .vtci file with correct VTC_SOCK_TYPE environment values
("quic" for QUIC listeners and "stream" for TCP listeners);
2025-12-08 10:40:59 +01:00
Frederic Lecaille
9c3180160d REGTESTS: quic: set_ssl_cafile.vtc supported by QUIC
ssl/set_ssl_cafile.vtc was renamed to ssl/set_ssl_cafile.vtci
to produce a common part runnable both for QUIC and TCP listeners.
Then set_ssl_cafile.vtc files were created both under ssl and quic directories
to call this .vtci file with correct VTC_SOCK_TYPE environment values
("quic" for QUIC listeners and "stream" for TCP listeners);
2025-12-08 10:40:59 +01:00
Frederic Lecaille
3f5e73e83f BUG/MINOR: quic-be: missing connection stream closure upon TLS alert to send
This is the same issue as the one fixed by this commit:
   BUG/MINOR: quic-be: handshake errors without connection stream closure
But this time this is when the client has to send an alert to the server.
The fix consists in creating the mux after having set the handshake connection
error flag and error_code.

This bug was revealed by ssl/set_ssl_cafile.vtc reg test.

Depends on this commit:
     MINOR: quic: avoid code duplication in TLS alert callback

Must be backported to 3.3
2025-12-08 10:40:59 +01:00
Frederic Lecaille
e7b06f5e7a MINOR: quic: avoid code duplication in TLS alert callback
Both the OpenSSL QUIC API TLS alert callback ha_quic_ossl_alert() does exactly
the same thing than the one for quictls API, even if the parameter have different
types.

Call ha_quic_send_alert() quictls callback from ha_quic_ossl_alert OpenSSL
QUIC API callback to avoid such code duplication.
2025-12-08 10:40:59 +01:00
Frederic Lecaille
ad101dc3d5 REGTESTS: quic: set_ssl_bug_2265.vtc supported by QUIC
ssl/set_ssl_bug_2265.vtc was renamed to ssl/set_ssl_bug_2265.vtci
to produce a common part runnable both for QUIC and TCP listeners.
Then set_ssl_bug_2265.vtc files were created both under ssl and quic directories
to call this .vtci file with correct VTC_SOCK_TYPE environment values
("quic" for QUIC listeners and "stream" for TCP listeners);
2025-12-08 10:40:59 +01:00
Frederic Lecaille
2e7320d2ee REGTESTS: quic: ocsp_auto_update.vtc supported by QUIC
ssl/ocsp_auto_update.vtc was renamed to ssl/ocsp_auto_update.vtci
to produce a common part runnable both for QUIC and TCP listeners.
Then ocsp_auto_update.vtc files were created both under ssl and quic directories
to call this .vtci file with correct VTC_SOCK_TYPE environment values
("quic" for QUIC listeners and "stream" for TCP listeners);
2025-12-08 10:40:59 +01:00
Frederic Lecaille
cdfd9b154a REGTESTS: quic: new_del_ssl_cafile.vtc supported by QUIC
ssl/new_del_ssl_cafile.vtc was rename to ssl/new_del_ssl_cafile.vtci
to produce a common part runnable both for QUIC and TCP connections.
Then new_del_ssl_cafile.vtc files were created both under ssl and quic directories
to call this .vtci file with correct VTC_SOCK_TYPE environment values
("quic" for QUIC connection and "stream" for TCP connections);
2025-12-08 10:40:59 +01:00
Frederic Lecaille
8c48a7798a REGTESTS: quic: issuers_chain_path.vtc supported by QUIC
ssl/issuers_chain_path.vtc was rename to ssl/issuers_chain_path.vtci
to produce a common part runnable both for QUIC and TCP connections.
Then issuers_chain_path.vtc files were created both under ssl and quic directories
to call this .vtci file with correct VTC_SOCK_TYPE environment values
("quic" for QUIC connection and "stream" for TCP connections);
2025-12-08 10:40:59 +01:00
Frederic Lecaille
94a7e0127b REGTESTS: quic: dynamic_server_ssl.vtc supported by QUIC
ssl/dynamic_server_ssl.vtc was rename to ssl/dynamic_server_ssl.vtci
to produce a common part runnable both for QUIC and TCP connections.
Then dynamic_server_ssl.vtc were created both under ssl and quic directories
to call the .vtci file with correct VTC_SOCK_TYPE environment value.

Note that VTC_SOCK_TYPE may be resolved in haproxy -cli { } sections.
2025-12-08 10:40:59 +01:00
Frederic Lecaille
588d0edf99 REGTESTS: quic/ssl: ssl/del_ssl_crt-list.vtc supported by QUIC
Extract from ssl/del_ssl_crt-list.vtc the common part to produce
ssl/del_ssl_crt-list.vtci which may be reused by QUIC and TCP
from respectively quic/del_ssl_crt-list.vtc and ssl/del_ssl_crt-list.vtc
thanks to "include" VTC command and VTC_SOCK_TYPE special vtest environment
variable.
2025-12-08 10:40:59 +01:00
Frederic Lecaille
6e94b69665 REGTESTS: ssl: Move all the SSL certificates, keys, crt-lists inside "certs" directory
Move all these files and others for OCSP tests found into reg-tests/ssl
to reg-test/ssl/certs and adapt all the VTC files which use them.

This patch is needed by other tests which have to include the SSL tests.
Indeed, some VTC commands contain paths to these files which cannot
be customized with environment variables, depending on the location the VTC file
is runi from, because VTC does not resolve the environment variables. Only macros
as ${testdir} can be resolved.

For instance this command run from a VTC file from reg-tests/ssl directory cannot
be reused from another directory, except if we add a symbolic link for each certs,
key etc.

 haproxy h1 -cli {
   send "del ssl crt-list ${testdir}/localhost.crt-list ${testdir}/common.pem:1"
 }

This is not what we want. We add a symbolic link to reg-test/ssl/certs to the
directory and modify the command above as follows:

 haproxy h1 -cli {
   send "del ssl crt-list ${testdir}/certs/localhost.crt-list ${testdir}/certs/common.pem:1"
 }
2025-12-08 10:40:59 +01:00
Frederic Lecaille
21293dd6c3 MINOR: quic: Add useful debugging traces in qc_idle_timer_do_rearm()
Traces were missing in this function.
Also add information about the connection struct from qc->conn when
initialized for all the traces.

Should be easily backported as far as 2.6.
2025-12-08 10:40:59 +01:00
Frederic Lecaille
c36e27d10e BUG/MINOR: quic-be: handshake errors without connection stream closure
This bug was revealed on backend side by reg-tests/ssl/del_ssl_crt-list.vtc when
run wich QUIC connections. As expected by the test, a TLS alert is generated on
servsr side. This latter sands a CONNECTION_CLOSE frame with a CRYPTO error
(>= 0x100). In this case the client closes its QUIC connection. But
the stream connection was not informed. This leads the connection to
be closed after the server timeout expiration. It shouls be closed asap.
This is the reason why reg-tests/ssl/del_ssl_crt-list.vtc could succeeds
or failed, but only after a 5 seconds delay.

To fix this, mimic the ssl_sock_io_cb() for TCP/SSL connections. Call
the same code this patch implements with ssl_sock_handle_hs_error()
to correctly handle the handshake errors. Note that some SSL counters
were not incremented for both the backends and frontends. After such
errors, ssl_sock_io_cb() start the mux after the connection has been
flagged in error. This has as side effect to close the stream
in conn_create_mux().

Must be backported to 3.3 only for backends. This is not sure at this time
if this bug may impact the frontends.
2025-12-08 10:40:59 +01:00
Frederic Lecaille
63273c795f BUG/MINOR: quic/ssl: crash in ClientHello callback ssl traces
Such crashes may occur for QUIC frontends only when the SSL traces are enabled.

ssl_sock_switchctx_cbk() ClientHello callback may be called without any connection
initialize (<conn>) for QUIC connections leading to crashes when passing
conn->err_code to TRACE_ERROR().

Modify the TRACE_ERROR() statement to pass this parameter only when <conn> is
initialized.

Must be backported as far as 3.2.
2025-12-08 10:40:59 +01:00
Willy Tarreau
d2a1665af0 DOC: config: reorder the cache section's keywords
Probably due to historical accumulation, keywords were in a random
order that doesn't help when looking them up. Let's just reorder them
in alphabetical order like other sections. This can be backported.
2025-12-04 15:44:38 +01:00
Willy Tarreau
4d0a88c746 DOC: config: mention clearer that the cache's total-max-size is mandatory
As reported in GH issue #3201, it's easy to overlook this, so let's make
it clearer by mentioning the keyword. This can be backported to all
versions.
2025-12-04 15:42:09 +01:00
Willy Tarreau
cd959f1321 BUG/MEDIUM: config: ignore empty args in skipped blocks
As returned by Christian Ruppert in GH issue #3203, we're having an
issue with checks for empty args in skipped blocks: the check is
performed after the line is tokenized, without considering the case
where it's disabled due to outer false .if/.else conditions. Because
of this, a test like this one:

    .if defined(SRV1_ADDR)
        server srv1 "$SRV1_ADDR"
    .endif

will fail when SRV1_ADDR is empty or not set, saying that this will
result in an empty arg on the line.

The solution consists in postponing this check after the conditions
evaluation so that disabled lines are already skipped. And for this
to be possible, we need to move "errptr" one level above so that it
remains accessible there.

This will need to be backported to 3.3 and wherever commit 1968731765
("BUG/MEDIUM: config: solve the empty argument problem again") is
backported. As such it is also related to GH issue #2367.
2025-12-04 15:33:43 +01:00
Willy Tarreau
b29560f610 BUG/MEDIUM: connection: fix "bc_settings_streams_limit" typo
The keyword was correct in the doc but in the code it was spelled
with a missing 's' after 'settings', making it unavailable. Since
there was no other way to find this but reading the code, it's safe
to simply fix it and assume nobody relied on the wrong spelling.

In the worst case for older backports it can also be duplicated.

This must be backported to 3.0.
2025-12-04 15:26:54 +01:00
William Lallemand
85689b072a REGTESTS: ssl: split tls*_reuse in stateless and stateful resume tests
Simplify ssl_reuse.vtci so it can be started with variables:

- SSL_CACHESIZE allow to specify the size of the session cache size for
  the frontend
- NO_TLS_TICKETS allow to specify the "no-tls-tickets" option on bind

It introduces these files:

- ssl/tls12_resume_stateful.vtc
- ssl/tls12_resume_stateless.vtc
- ssl/tls13_resume_stateless.vtc
- ssl/tls13_resume_stateful.vtc
- quic/tls13_resume_stateless.vtc
- quic/tls13_resume_stateful.vtc
- quic/tls13_0rtt_stateful.vtc
- quic/tls13_0rtt_stateless.vtc

stateful files have "no-tls-tickets" + tune.tls.cachesize 20000
stateless files have "tls-tickets" + tune.tls.cachesize 0

This allows to enable AWS-LC on TCP TLS1.2 and TCP TL1.3+tickets.

TLS1.2+stateless does not seem to work on WolfSSL.
2025-12-04 15:05:56 +01:00
William Lallemand
c7b5d2552a REGTESTS: ssl enable tls12_reuse.vtc for AWS-LC
The TLS resume test was never started with AWS-LC because the TLS1.3
part was not working. Since we split the reg-tests with a TLS1.2 part
and a TLS1.3 part, we can enable the tls1.2 part for AWS-LC.
2025-12-04 11:40:04 +01:00
Frederic Lecaille
cdca48b88c BUG/MINOR: quic-be: Missing keywords array NULL termination
This bug arrived with this commit:
     MINOR: quic: implement cc-algo server keyword
where <srv> keywords list with a missing array NULL termination inside was
introduced to parse the QUIC backend CC algorithms.

Detected by ASAN during ssl/add_ssl_crt-list.vtc execution as follows:

***  h1    debug|==4066081==ERROR: AddressSanitizer: global-buffer-overflow on address 0x5562e31dedb8 at pc 0x5562e298951f bp 0x7ffe9f9f2b40 sp 0x7ffe9f9f2b38
***  h1    debug|READ of size 8 at 0x5562e31dedb8 thread T0
**** dT    0.173
***  h1    debug|    #0 0x5562e298951e in srv_find_kw src/server.c:789
***  h1    debug|    #1 0x5562e2989630 in _srv_parse_kw src/server.c:3847
***  h1    debug|    #2 0x5562e299db1f in parse_server src/server.c:4024
***  h1    debug|    #3 0x5562e2c86ea4 in cfg_parse_listen src/cfgparse-listen.c:593
***  h1    debug|    #4 0x5562e2b0ede9 in parse_cfg src/cfgparse.c:2708
***  h1    debug|    #5 0x5562e2c47d48 in read_cfg src/haproxy.c:1077
***  h1    debug|    #6 0x5562e2682055 in main src/haproxy.c:3366
***  h1    debug|    #7 0x7ff3ff867249 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
***  h1    debug|    #8 0x7ff3ff867304 in __libc_start_main_impl ../csu/libc-start.c:360
***  h1    debug|    #9 0x5562e26858d0 in _start (/home/flecaille/src/haproxy/haproxy+0x2638d0)
***  h1    debug|
***  h1    debug|0x5562e31dedb8 is located 40 bytes to the left of global variable 'bind_kws' defined in 'src/cfgparse-quic.c:255:28' (0x5562e31dede0) of size 120
***  h1    debug|0x5562e31dedb8 is located 0 bytes to the right of global variable 'srv_kws' defined in 'src/cfgparse-quic.c:264:27' (0x5562e31ded80) of size 56
***  h1    debug|SUMMARY: AddressSanitizer: global-buffer-overflow src/server.c:789 in srv_find_kw
***  h1    debug|Shadow bytes around the buggy address:
***  h1    debug|  0x0aacdc633d60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
***  h1    debug|  0x0aacdc633d70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
***  h1    debug|  0x0aacdc633d80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
***  h1    debug|  0x0aacdc633d90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
***  h1    debug|  0x0aacdc633da0: 00 00 00 00 00 00 00 00 00 00 f9 f9 f9 f9 f9 f9
***  h1    debug|=>0x0aacdc633db0: 00 00 00 00 00 00 00[f9]f9 f9 f9 f9 00 00 00 00
***  h1    debug|  0x0aacdc633dc0: 00 00 00 00 00 00 00 00 00 00 00 f9 f9 f9 f9 f9
***  h1    debug|  0x0aacdc633dd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
***  h1    debug|  0x0aacdc633de0: 00 00 00 00 00 00 00 00 f9 f9 f9 f9 f9 f9 f9 f9
***  h1    debug|  0x0aacdc633df0: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
***  h1    debug|  0x0aacdc633e00: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
***  h1    debug|Shadow byte legend (one shadow byte represents 8 application bytes):

This should be backported where the commit above is supposed to be backported.
2025-12-03 11:07:47 +01:00
Amaury Denoyelle
47dff5be52 MINOR: quic: implement cc-algo server keyword
Extend QUIC server configuration so that congestion algorithm and
maximum window size can be set on the server line. This can be achieved
using quic-cc-algo keyword with a syntax similar to a bind line.

This should be backported up to 3.3 as this feature is considered as
necessary for full QUIC backend support. Note that this relies on the
serie of previous commits which should be picked first.
2025-12-01 15:53:58 +01:00
Amaury Denoyelle
4f43abd731 MINOR: quic: extract cc-algo parsing in a dedicated function
Extract code from bind_parse_quic_cc_algo() related to pure parsing of
quic-cc-algo keyword. The objective is to be able to quickly duplicate
this option on the server line.

This may need to be backported to support QUIC congestion control
algorithm support on the server line in version 3.3.
2025-12-01 15:06:01 +01:00
Amaury Denoyelle
979588227f MINOR: quic: define quic_cc_algo as const
Each QUIC congestion algorithm is defined as a structure with callbacks
in it. Every quic_conn has a member pointing to the configured
algorithm, inherited from the bind-conf keyword or to the default CUBIC
value.

Convert all these definitions to const. This ensures that there never
will be an accidental modification of a globally shared structure. This
also requires to mark quic_cc_algo field in bind_conf and quic_cc as
const.
2025-12-01 15:05:41 +01:00
Amaury Denoyelle
acbb378136 Revert "MINOR: quic: use dynamic cc_algo on bind_conf"
This reverts commit a6504c9cfb6bb48ae93babb76a2ab10ddb014a79.

Each supported QUIC algo are associated with a set of callbacks defined
in a structure quic_cc_algo. Originally, bind_conf would use a constant
pointer to one of these definitions.

During pacing implementation, this field was transformed into a
dynamically allocated value copied from the original definition. The
idea was to be able to tweak settings at the listener level. However,
this was never used in practice. As such, revert to the original model.

This may need to be backported to support QUIC congestion control
algorithm support on the server line in version 3.3.
2025-12-01 14:18:58 +01:00
William Lallemand
c641ea4f9b DOC: configuration: ECH support details
Specify which OpenSSL branch is supported and that AWS-LC is not
supported.

Must be backported to 3.3.
2025-11-30 09:47:56 +01:00
Remi Tricot-Le Breton
2b3d13a740 BUG/MINOR: jwt: Missing "case" in switch statement
Because of missing "case" keyword in front of the values in a switch
case statement, the values were interpreted as goto tags and the switch
statement became useless.

This patch should fix GitHub issue #3200.
The fix should be backported up to 2.8.
2025-11-28 16:36:46 +01:00
Willy Tarreau
36133759d3 [RELEASE] Released version 3.4-dev0
Released version 3.4-dev0 with the following main changes :
    - MINOR: version: mention that it's development again
2025-11-26 16:12:45 +01:00
Willy Tarreau
e8d6ffb692 MINOR: version: mention that it's development again
This essentially reverts d8ba9a2a92.
2025-11-26 16:11:47 +01:00
Willy Tarreau
7832fb21fe [RELEASE] Released version 3.3.0
Released version 3.3.0 with the following main changes :
    - BUG/MINOR: acme: better challenge_ready processing
    - BUG/MINOR: acme: warning ‘ctx’ may be used uninitialized
    - MINOR: httpclient: complete the https log
    - BUG/MEDIUM: server: do not use default SNI if manually set
    - BUG/MINOR: freq_ctr: Prevent possible signed overflow in freq_ctr_overshoot_period
    - DOC: ssl: Document the restrictions on 0RTT.
    - DOC: ssl: Note that 0rtt works fork QUIC with QuicTLS too.
    - BUG/MEDIUM: quic: do not prevent sending if no BE token
    - BUG/MINOR: quic/server: free quic_retry_token on srv drop
    - MINOR: quic: split global CID tree between FE and BE sides
    - MINOR: quic: use separate global quic_conns FE/BE lists
    - MINOR: quic: add "clo" filter on show quic
    - MINOR: quic: dump backend connections on show quic
    - MINOR: quic: mark backend conns on show quic
    - BUG/MINOR: quic: fix uninit list on show quic handler
    - BUG/MINOR: quic: release BE quic_conn on connect failure
    - BUG/MINOR: server: fix srv_drop() crash on partially init srv
    - BUG/MINOR: h3: do no crash on forwarding multiple chained response
    - BUG/MINOR: h3: handle properly buf alloc failure on response forwarding
    - BUG/MEDIUM: server/ssl: Unset the SNI for new server connections if none is set
    - BUG/MINOR: acme: fix ha_alert() call
    - Revert "BUG/MEDIUM: server/ssl: Unset the SNI for new server connections if none is set"
    - BUG/MINOR: sock-inet: ignore conntrack for transparent sockets on Linux
    - DEV: patchbot: prepare for new version 3.4-dev
    - DOC: update INSTALL with the range of gcc compilers and openssl versions
    - MINOR: version: mention that 3.3 is stable now
2025-11-26 15:55:57 +01:00
Willy Tarreau
d8ba9a2a92 MINOR: version: mention that 3.3 is stable now
This version will be maintained up to around Q1 2027. The INSTALL file
also mentions it.
2025-11-26 15:54:30 +01:00
Willy Tarreau
09dd6bb4cb DOC: update INSTALL with the range of gcc compilers and openssl versions
Gcc 4.7 to 15 are tested. OpenSSL was tested up to 3.6. QUIC support
requires OpenSSL >= 3.5.2.
2025-11-26 15:50:43 +01:00
Willy Tarreau
22fd296a04 DEV: patchbot: prepare for new version 3.4-dev
The bot will now load the prompt for the upcoming 3.4 version so we have
to rename the files and update their contents to match the current version.
2025-11-26 15:35:22 +01:00
Willy Tarreau
e5658c52d0 BUG/MINOR: sock-inet: ignore conntrack for transparent sockets on Linux
As reported in github issue #3192, in certain situations with transparent
listeners, it is possible to get the incoming connection's destination
wrong via SO_ORIGINAL_DST. Two cases were identified thus far:
  - incorrect conntrack configuration where NOTRACK is used only on
    incoming packets, resulting in reverse connections being created
    from response packets. It's then mostly a matter of timing, i.e.
    whether or not the connection is confirmed before the source is
    retrieved, but in this case the connection's destination address
    as retrieved by SO_ORIGINAL_DST is the client's address.

  - late outgoing retransmit that recreates a just expired conntrack
    entry, in reverse direction as well. It's possible that combinations
    of RST or FIN might play a role here in speeding up conntrack eviction,
    as well as the rollover of source ports on the client whose new
    connection matches an older one and simply refreshes it due to
    nf_conntrack_tcp_loose being set by default.

TPROXY doesn't require conntrack, only REDIRECT, DNAT etc do. However
the system doesn't offer any option to know how a conntrack entry was
created (i.e. normally or via a response packet) to let us know that
it's pointless to check the original destination, nor does it permit
to access the local vs peer addresses in opposition to src/dst which
can be wrong in this case.

One alternate approach could consist in only checking SO_ORIGINAL_DST
for listening sockets not configured with the "transparent" option,
but the problem here is that our low-level API only works with FDs
without knowing their purpose, so it's unknown there that the fd
corresponds to a listener, let alone in transparent mode.

A (slightly more expensive) variant of this approach here consists in
checking on the socket itself that it was accepted in transparent mode
using IP_TRANSPARENT, and skip SO_ORIGINAL_DST if this is the case.
This does the job well enough (no more client addresses appearing in
the dst field) and remains a good compromise. A future improvement of
the API could permit to pass the transparent flag down the stack to
that function.

This should be backported to stable versions after some observation
in latest -dev.

For reference, here are some links to older conversations on that topic
that Lukas found during this analysis:

  https://lists.openwall.net/netdev/2019/01/12/34
  https://discourse.haproxy.org/t/send-proxy-not-modifying-some-traffic-with-proxy-ip-port-details/3336/9
  https://www.mail-archive.com/haproxy@formilux.org/msg32199.html
  https://lists.openwall.net/netdev/2019/01/23/114
2025-11-26 13:43:58 +01:00
Christopher Faulet
7d9cc28f92 Revert "BUG/MEDIUM: server/ssl: Unset the SNI for new server connections if none is set"
This reverts commit de29000e602bda55d32c266252ef63824e838ac0.

The fix was in fact invalid. First it is not supprted by WolfSSL to call
SSL_set_tlsext_host_name with a hostname to NULL. Then, it is not specified
as supported by other SSL libraries.

But, by reviewing the root cause of this bug, it appears there is an issue
with the reuse of TLS sesisons. It must not be performed if the SNI does not
match. A TLS session created with a SNI must not be reused with another
SNI. The side effects are not clear but functionnaly speaking, it is
invalid.

So, for now, the commit above was reverted because it is invalid and it
crashes with WolfSSL. Then the init of the SSL connection must be reworked
to get the SNI earlier, to be able to reuse or not an existing TLS
session.
2025-11-26 12:05:43 +01:00
Maxime Henrion
d506c03aa0 BUG/MINOR: acme: fix ha_alert() call
A NULL pointer was passed as the format string, so this alert message
was never written.

Must be backported to 3.2.
2025-11-25 20:20:25 +01:00
Christopher Faulet
de29000e60 BUG/MEDIUM: server/ssl: Unset the SNI for new server connections if none is set
When a new SSL server connection is created, if no SNI is set, it is
possible to inherit from the one of the reused TLS session. The bug was
introduced by the commit 95ac5fe4a ("MEDIUM: ssl_sock: always use the SSL's
server name, not the one from the tid"). The mixup is possible between
regular connections but also with health-checks connections.

To fix the issue, when no SNI is set, for regular server connections and for
health-check connections, the SNI must explicitly be disabled by calling
ssl_sock_set_servername() with the hostname set to NULL.

Many thanks to Lukas for his detailed bug report.

This patch should fix the issue #3195. It must be backported as far as 3.0.
2025-11-25 16:32:46 +01:00
Amaury Denoyelle
a70816da82 BUG/MINOR: h3: handle properly buf alloc failure on response forwarding
Replace BUG_ON() for buffer alloc failure on h3_resp_headers_to_htx() by
proper error handling. An error status is reported which should be
sufficient to initiate connection closure.

No need to backport.
2025-11-25 15:55:08 +01:00
Amaury Denoyelle
ae96defaca BUG/MINOR: h3: do no crash on forwarding multiple chained response
h3_resp_headers_to_htx() is the function used to convert an HTTP/3
response into a HTX message. It was introduced on this release for QUIC
backend support.

A BUG_ON() would occur if multiple responses are forwarded
simultaneously on a stream without rcv_buf in between. Fix this by
removing it. Instead, if QCS HTX buffer is not empty when handling with
a new response, prefer to pause demux operation. This is restarted when
the buffer has been read and emptied by the upper stream layer.

No need to backport.
2025-11-25 15:52:37 +01:00
Amaury Denoyelle
a363b536a9 BUG/MINOR: server: fix srv_drop() crash on partially init srv
A recent patch has introduced free operation for QUIC tokens stored in a
server. These values are located in <per_thr> server array.

However, a server instance may be released prior to its full
initialization in case of a failure during "add server" CLI command. The
mentionned patch would cause a srv_drop() crash due to an invalid usage
of NULL <per_thr> member.

Fix this by adding a check on <per_thr> prior to dereference it in
srv_drop().

No need to backport.
2025-11-25 15:16:13 +01:00
Amaury Denoyelle
6c08eb7173 BUG/MINOR: quic: release BE quic_conn on connect failure
If quic_connect_server() fails, quic_conn FD will remain unopened as set
to -1. Backend connections do not have a fallback socket for future
exchange, contrary to frontend one which can use the listener FD. As
such, it is better to release these connections early.

This patch adjusts such failure by extending quic_close(). This function
is called by the upper layer immediately after a connect issue. In this
case, release immediately a quic_conn backend instance if the FD is
unset, which means that connect has previously failed.

Also, quic_conn_release() is extended to ensure that such faulty
connections are immediately freed and not converted into a
quic_conn_closed instance.

Prior to this patch, a backend quic_conn without any FD would remain
allocated and possibly active. If its tasklet is executed, this resulted
in a crash due to access to an invalid FD.

No need to backport.
2025-11-25 14:50:23 +01:00
Amaury Denoyelle
346631700d BUG/MINOR: quic: fix uninit list on show quic handler
A recent patch has extended "show quic" capability. It is now possible
to list a specific list of connections, either active frontend, closing
frontend or backend connections.

An issue was introduced as the list is local storage. As this command is
reentrant, show quic context must be extended so that the currently
inspected list is also saved.

This issue was reported via GCC which mentions an uninitilized value
depending on branching conditions.
2025-11-25 14:50:19 +01:00
Amaury Denoyelle
a3f76875f4 MINOR: quic: mark backend conns on show quic
Add an extra "(B)" marker when displaying a backend connection during a
"show quic". This is useful to differentiate them with the frontend side
when displaying all connections.
2025-11-25 14:31:27 +01:00
Amaury Denoyelle
e56fdf6320 MINOR: quic: dump backend connections on show quic
Add a new "be" filter to "show quic". Its purpose is to be able to
display backend connections. These connections can also be listed using
"all" filter.
2025-11-25 14:30:18 +01:00
Amaury Denoyelle
3685681373 MINOR: quic: add "clo" filter on show quic
Add a new filter "clo" for "show quic" command. Its purpose is to filter
output to only list closing frontend connections.
2025-11-25 14:30:18 +01:00
Amaury Denoyelle
49e6fca51b MINOR: quic: use separate global quic_conns FE/BE lists
Each quic_conn instance is stored in a global list. Its purpose is to be
able to loop over all known connections during "show quic".

Split this into two separate lists for frontend and backend usage.
Another change is that closing backend connections do not move into
quic_conns_clo list. They remain instead in their original list. The
objective of this patch is to reduce the contention between the two
sides.

Note that this prevents backend connections to be listed in "show quic"
now. This will be adjusted in a future patch.
2025-11-25 14:30:18 +01:00
Amaury Denoyelle
a5801e542d MINOR: quic: split global CID tree between FE and BE sides
QUIC CIDs are stored in a global tree. Prior to this patch, CIDs used on
both frontend and backend sides were mixed together.

This patch implement CID storage separation between FE and BE sides. The
original tre quic_cid_trees is splitted as
quic_fe_cid_trees/quic_be_cid_trees.

This patch should reduce contention between frontend and backend usages.
Also, it should reduce the risk of random CID collision.
2025-11-25 14:30:18 +01:00
Amaury Denoyelle
4b596c1ea8 BUG/MINOR: quic/server: free quic_retry_token on srv drop
A recent patch has implemented caching of QUIC token received from a
NEW_TOKEN frame into the server cache. This value is stored per thread
into a <quic_retry_token> field.

This field is an ist, first set to an empty string. Via
qc_try_store_new_token(), it is reallocated to fit the size of the newly
stored token. Prior to this patch, the field was never freed so this
causes a memory leak.

Fix this by using istfree() on <quic_retry_token> field during
srv_drop().

No need to backport.
2025-11-25 14:30:18 +01:00
Amaury Denoyelle
cbfe574d8a BUG/MEDIUM: quic: do not prevent sending if no BE token
For QUIC client support, a token may be emitted along with INITIAL
packets during the handshake. The token is encoded during emission via
qc_enc_token() called by qc_build_pkt().

The token may be provided from different sources. First, it can be
retrieved via <retry_token> quic_conn member when a Retry packet was
received. If not present, a token may be reused from the server cache,
populated from NEW_TOKEN received from previous a connection.

Prior to this patch, the last method may cause an issue. If the upper
connection instance is released prior to the handshake completion, this
prevents access to a possible server token. This is considered an error
by qc_enc_token(). The error is reported up to calling functions,
preventing any emission to be performed. In the end, this prevented the
either the full quic_conn release or subsizing into quic_conn_closed
until the idle timeout completion (30s by default). With abortonclose
set now by default on HTTP frontends, early client shutdowns can easily
cause excessive memory consumption.

To fix this, change qc_enc_token() so that if connection is closed, no
token is encoded but also no error is reported. This allows to continue
emission and permit early connection release.

No need to backport.
2025-11-25 14:30:18 +01:00
Olivier Houchard
e27216b799 DOC: ssl: Note that 0rtt works fork QUIC with QuicTLS too.
Document that one can use 0rtt with QUIC when using QuicTLS too.
2025-11-25 13:17:45 +01:00
Olivier Houchard
f867068dc7 DOC: ssl: Document the restrictions on 0RTT.
Document that with QUIC, 0RTT only works with OpenSSL >= 3.5.2 and
AWS-LC, and for TLS/TCP, it only works with OpenSSL, and frontends
require that an ALPN be sent by the client to use the early data before
the handshake.
2025-11-25 11:46:22 +01:00
Jacques Heunis
91eb9b082b BUG/MINOR: freq_ctr: Prevent possible signed overflow in freq_ctr_overshoot_period
All of the other bandwidth-limiting code stores limits and intermediate
(byte) counters as unsigned integers. The exception here is
freq_ctr_overshoot_period which takes in unsigned values but returns a
signed value. While this has the benefit of letting the caller know how
far away from overshooting they are, this is not currently leveraged
anywhere in the codebase, and it has the downside of halving the positive
range of the result.

More concretely though, returning a signed integer when all intermediate
values are unsigned (and boundaries are not checked) could result in an
overflow, producing values that are at best unexpected. In the case of
flt_bwlim (the only usage of freq_ctr_overshoot_period in the codebase at
the time of writing), an overflow could cause the filter to wait for a
large number of milliseconds when in fact it shouldn't wait at all.

This is a niche possibility, because it requires that a bandwidth limit is
defined in the range [2^31, 2^32). In this case, the raw limit value would
not fit into a signed integer, and close to the end of the period, the
`(elapsed * freq)/period` calculation could produce a value which also
doesn't fit into a signed integer.

If at the same time `curr` (the number of events counted so far in the
current period) is small, then we could get a very large negative value
which overflows. This is undefined behaviour and could produce surprising
results. The most obvious outcome is flt_bwlim sometimes waiting for a
large amount of time in a case where it shouldn't wait at all, thereby
incorrectly slowing down the flow of data.

Converting just the return type from signed to unsigned (and checking for
the overflow) prevents this undefined behaviour. It also makes the range
of valid values consistent between the input and output of
freq_ctr_overshoot_period and with the input and output of other freq_ctr
functions, thereby reducing the potential for surprise in intermediate
calculations: now everything supports the full 0 - 2^32 range.
2025-11-24 14:10:13 +01:00
Amaury Denoyelle
2829165f61 BUG/MEDIUM: server: do not use default SNI if manually set
A new server feature "sni-auto" has been introduced recently. The
objective is to automatically set the SNI value to the host header if no
SNI is explicitely set.

  668916c1a2fc2180028ae051aa805bb71c7b690b
  MEDIUM: server/ssl: Base the SNI value to the HTTP host header by default

There is an issue with it : server SNI is currently always overwritten,
even if explicitely set in the configuration file. Adjust
check_config_validity() to ensure the default value is only used if
<sni_expr> is NULL.

This issue was detected as a memory leak on <sni_expr> was reported when
SNI is explicitely set on a server line.

This patch is related to github feature request #3081.

No need to backport, unless the above patch is.
2025-11-24 11:45:18 +01:00
William Lallemand
5dbf06e205 MINOR: httpclient: complete the https log
The httpsclient_log_format variable lacks a few values in the TLS fields
that are now available as fetches.

On the backend side we have:

"%[fc_err]/%[ssl_fc_err,hex]/%[ssl_c_err]/%[ssl_c_ca_err]/%[ssl_fc_is_resumed] %[ssl_fc_sni]/%sslv/%sslc"

We now have enough sample fetches to have this equivalent in the
httpclient:

"%[bc_err]/%[ssl_bc_err,hex]/%[ssl_c_err]/%[ssl_c_ca_err]/%[ssl_bc_is_resumed] %[ssl_bc_sni]/%[ssl_bc_protocol]/%[ssl_bc_cipher]"

Instead of the current:

"%[bc_err]/%[ssl_bc_err,hex]/-/-/%[ssl_bc_is_resumed] -/-/-"
2025-11-22 12:29:33 +01:00
William Lallemand
0cae2f0515 BUG/MINOR: acme: warning ‘ctx’ may be used uninitialized
Please compiler with maybe-uninitialized warning

src/acme.c: In function ‘cli_acme_chall_ready_parse’:
include/haproxy/task.h:215:9: error: ‘ctx’ may be used uninitialized [-Werror=maybe-uninitialized]
  215 |         _task_wakeup(t, f, MK_CALLER(WAKEUP_TYPE_TASK_WAKEUP, 0, 0))
      |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/acme.c:2903:17: note: in expansion of macro ‘task_wakeup’
 2903 |                 task_wakeup(ctx->task, TASK_WOKEN_MSG);
      |                 ^~~~~~~~~~~
src/acme.c:2862:26: note: ‘ctx’ was declared here
 2862 |         struct acme_ctx *ctx;
      |                          ^~~

Backport to 3.2.
2025-11-21 23:04:16 +01:00
William Lallemand
d77d3479ed BUG/MINOR: acme: better challenge_ready processing
Improve the challenge_ready processing:

- do a lookup directly instead looping in the task tree
- only do a task_wakeup when every challenges are ready to avoid starting
  the task and stopping it just after
- Compute the number of remaining challenge to setup
- Output a message giving the number of remaining challenges to setup
  and if the task started again.

Backport to 3.2.
2025-11-21 22:47:52 +01:00
Willy Tarreau
8418c001ce [RELEASE] Released version 3.3-dev14
Released version 3.3-dev14 with the following main changes :
    - MINOR: stick-tables: Rename stksess shards to use buckets
    - MINOR: quic: do not use quic_newcid_from_hash64 on BE side
    - MINOR: quic: support multiple random CID generation for BE side
    - MINOR: quic: try to clarify quic_conn CIDs fields direction
    - MINOR: quic: refactor qc_new_conn() prototype
    - MINOR: quic: remove <ipv4> arg from qc_new_conn()
    - MEDIUM: mworker: set the mworker-max-reloads to 50
    - BUG/MEDIUM: quic-be: prevent use of MUX for 0-RTT sessions without secrets
    - CLEANUP: startup: move confusing msg variable
    - BUG/MEDIUM: mworker: signals inconsistencies during startup and reload
    - BUG/MINOR: mworker: wrong signals during startup
    - BUG/MINOR: acme: P-256 doesn't work with openssl >= 3.0
    - REGTESTS: ssl: split the SSL reuse test into TLS 1.2/1.3
    - BUILD: Makefile: make install with admin tools
    - CI: github: make install-bin instead of make install
    - BUG/MINOR: ssl: remove dead code in ssl_sock_from_buf()
    - BUG/MINOR: mux-quic: implement max-reuse server parameter
    - MINOR: quic: fix trace on quic_conn_closed release
    - BUG/MINOR: quic: do not decrement jobs for backend conns
    - BUG/MINOR: quic: fix FD usage for quic_conn_closed on backend side
    - BUILD: Makefile: remove halog from install-admin
    - REGTESTS: ssl: add basic 0rtt tests for TLSv1.2, TLSv1.3 and QUIC
    - REGTESTS: ssl: also verify that 0-rtt properly advertises early-data:1
    - MINOR: quic/flags: add missing QUIC flags for flags dev tool.
    - MINOR: quic: uneeded xprt context variable passed as parameter
    - MINOR: limits: keep a copy of the rough estimate of needed FDs in global struct
    - MINOR: limits: explain a bit better what to do when fd limits are exceeded
    - BUG/MEDIUM: quic-be/ssl_sock: TLS callback called without connection
    - BUG/MINOR: acme: alert when the map doesn't exist at startup
    - DOC: acme: add details about the DNS-01 support
    - DOC: acme: explain how to dump the certificates
    - DOC: acme: configuring acme needs a crt file
    - DOC: acme: add details about key pair generation in ACME section
    - BUG/MEDIUM: queues: Don't forget to unlock the queue before exiting
    - MINOR: muxes: Support an optional ALPN string when defining mux protocols
    - MINOR: config: Do proto detection for listeners before checks about ALPN
    - BUG/MEDIUM: config: Use the mux protocol ALPN by default for listeners if forced
    - DOC: config: Add a note about conflict with ALPN/NPN settings and proto keyword
    - MINOR: quic: store source address for backend conns
    - BUG/MINOR: quic: flag conn with CO_FL_FDLESS on backend side
    - ADMIN: dump-certs: let dry-run compare certificates
    - BUG/MEDIUM: connection/ssl: also fix the ssl_sock_io_cb() regarding idle list
    - DOC: http: document 413 response code
    - MINOR: limits: display the computed maxconn using ha_notice()
    - BUG/MEDIUM: applet: Fix conditions to detect spinning loop with the new API
    - BUG/MEDIUM: cli: State the cli have no more data to deliver if it yields
    - MINOR: h3: adjust sedesc update for known input payload len
    - BUG/MINOR: mux-quic: fix sedesc leak on BE side
    - OPTIM: mux-quic: delay FE sedesc alloc to stream creation
    - BUG/MEDIUM: quic-be: quic_conn_closed buffer overflow
    - BUG/MINOR: mux-quic: check access on qcs stream-endpoint
    - BUG/MINOR: acme: handle multiple auth with the same name
    - BUG/MINOR: acme: prevent creating map entries with dns-01
2025-11-21 14:13:44 +01:00
William Lallemand
548e7079cd BUG/MINOR: acme: prevent creating map entries with dns-01
We don't need map entries with dns-01.

The patch must be backported to 3.2.
2025-11-21 12:28:41 +01:00
William Lallemand
26093121a3 BUG/MINOR: acme: handle multiple auth with the same name
In case of the dns-01 challenge, it is possible to have a domain
"example.com" and "*.example.com" in the same request. This will create
2 different auth objects, which need 2 different challenges.

However the associated domain is "example.com" for both auth objects.

When doing a "challenge_ready", the algorithm will break at the first
domain found. But since you can have multiple time the same domain in
this case, breaking at the first one prevent to have all auth objects in
a ready state.

This patch just remove the break so we can loop on every auth objects.

Must be backported to 3.2.
2025-11-21 12:28:41 +01:00
Amaury Denoyelle
bbd83e3de9 BUG/MINOR: mux-quic: check access on qcs stream-endpoint
Since the following commit, allocation of stream-endpoint has been
delayed. The objective is to allocate it only for QCS attached to an
upper stream object.

  commit e6064c561684d9b079e3b5725d38dc3b5c1b5cd5
  OPTIM: mux-quic: delay FE sedesc alloc to stream creation

However, some MUX functions are unsafe as qcs->sd is dereferenced
without any check on it which will result in a crash. Fix this by
testing that qcs->sd is allocated before using it.

This does not need to be backported, unless the above patch is.
2025-11-21 11:16:07 +01:00
Frederic Lecaille
91f479604e BUG/MEDIUM: quic-be: quic_conn_closed buffer overflow
This bug impacts only the backends.

Recent commits have modified quic_rx_pkt_parse() for the QUIC backend to handle the
retry token, and version negotiation. This function is called for the quic_conn
even when is closing state (so for the quic_conn_closed struct). The quic_conn
struct and quic_conn_closed struct share some members thank to the leading
QUIC_CONN_COMMON struct. The recent modification impacts some members which do not
exist for the quic_connn_closed struct, leading to buffer overflows if modified.

For the backends only this patch:
  1- silently drops the Retry packet (received/parsed only by backends)
  2- silently drops the Initial packets received in closing state

This is safe for the Initial packets because in closing state the datagrams
are entirely skipped thanks to qc_rx_check_closing() in quic_dgram_parse().

No backport needed because the backend support arrived with the current dev.
2025-11-21 10:49:44 +01:00
Amaury Denoyelle
e6064c5616 OPTIM: mux-quic: delay FE sedesc alloc to stream creation
On frontend side, a stream-endpoint is allocated on every qcs_new()
invokation. However, this is only used for bidirectional request
streams.

This patch delays stream-endpoint allocation to qcs_attach_sc(), just
prior the instantiation of the upper stream object. This does not bring
any behavior change but is a nice optimization.
2025-11-21 10:34:08 +01:00
Amaury Denoyelle
4fb8908605 BUG/MINOR: mux-quic: fix sedesc leak on BE side
On backend side, streams are instantiated prior to their QCS MUX
counterpart. Thus, QCS can reuse the stream-endpoint already allocated
with the streams, either on qmux_init() or attach operation.

However, a stream-endpoint is also always allocated in every qcs_new()
invokation. For backend QCS, it is thus overwritten on
qmux_init()/attach operation. This causes a memleak.

Fix this by restricting allocation of stream-endpoint only for frontend
connection.

This does not need to be backported.
2025-11-21 10:34:08 +01:00
Amaury Denoyelle
9f16c64a8c MINOR: h3: adjust sedesc update for known input payload len 2025-11-21 10:34:08 +01:00
Christopher Faulet
0629ce8f4b BUG/MEDIUM: cli: State the cli have no more data to deliver if it yields
A regression was introduced in the commit 2d7e3ddd4 ("BUG/MEDIUM: cli: do
not return ACKs one char at a time"). When the CLI is processing a command
line, we no longer send response immediately. It is especially useful for
clients sending a bunch of commands with very short response.

However, in that state, the CLI applet must state it has no more data to
deliver. Otherwise it will be woken up again and again because data are
found in its output buffer with no blocking conditions. In worst cases, if
the command rate is really high, this can trigger the watchdog.

This patch must be backported where the patch above is, so probably as far
as 3.0.
2025-11-21 10:00:15 +01:00
Christopher Faulet
dfdccbd2af BUG/MEDIUM: applet: Fix conditions to detect spinning loop with the new API
There was a mixup between read/send events and ability for an applet to
receive and send. The fix seems obvious by reading it. The call-rate must be
incremented when nothing was received from the applet while it was allowed
and nothing was sent to the applet while it was allowed.

This patch must be backported as far as 3.0.
2025-11-21 09:41:05 +01:00
Willy Tarreau
4cbff2cad9 MINOR: limits: display the computed maxconn using ha_notice()
The computed maxconn was only displayed in verbose or debug modes. This
is too bad because lots of users just don't know what they're starting
with and can be trapped when an environment changes. Let's use ha_notice()
instead of a conditional fprintf() so that it gets displayed right after
the other startup messages, hoping that users will get used to seeing it
and more easily spot anomalies. See github issue #3191 for more context.
2025-11-20 18:38:09 +01:00
Lukas Tribus
a50c074b74 DOC: http: document 413 response code
Considering that we only use a "413 Payload Too Large" response in a single
situation with a specific config toogle (h1-accept-payload-with-any-method),
add some text to make it easier to find.

Should be backported to 2.6.

Link: https://github.com/cbonte/haproxy-dconv/issues/46
Link: https://discourse.haproxy.org/t/haproxy-error-413-paylod-too-large/9831/3
2025-11-20 18:07:01 +01:00
Willy Tarreau
05c409f1be BUG/MEDIUM: connection/ssl: also fix the ssl_sock_io_cb() regarding idle list
The fix in commit 9481cef948 ("BUG/MEDIUM: connection: do not reinsert a
purgeable conn in idle list") is also needed for ssl_sock_io_cb() which
can also release an idle connection and must perform the same checks.
This fix must be backported to all stable versions containing the fix
above.
2025-11-20 17:19:50 +01:00
William Lallemand
6aa236e964 ADMIN: dump-certs: let dry-run compare certificates
Let the --dry-run mode connect to the socket and compare the
certificates. It would exits the process just before trying to move
the previous certificate and replace it.

This allow to have the "[NOTICE] (1234) XXX is already up to date" message
with dry-run.
2025-11-20 16:50:20 +01:00
Amaury Denoyelle
b2664d4450 BUG/MINOR: quic: flag conn with CO_FL_FDLESS on backend side
Connection struct defines an handle which can point to either a FD or a
quic_conn. On the latter case, CO_FL_FDLESS must be set. This is already
the case on frontend side.

This patch fixes QUIC backend support. Before setting connection handle
member to a quic_conn instance, ensure that CO_FL_FDLESS flag is set on
the connection.

Prior to this patch, crash can occur in "show sess all".

No need to backport.
2025-11-20 16:44:03 +01:00
Amaury Denoyelle
cd2962ee64 MINOR: quic: store source address for backend conns
quic_conn has a local_addr member which is used to store the connection
source address. On backend side, this member is initialized to NULL as
the address is not yet known prior to connect. With this patch,
quic_connect_server() is extended so that local_addr is updated after
connect() success.

Also, quic_sock_get_src() is completed for the backend side which now
returns local_addr member. This step is necessary to properly support
fetches bc_src/bc_src_port.
2025-11-20 16:44:03 +01:00
Christopher Faulet
a14b7790ad DOC: config: Add a note about conflict with ALPN/NPN settings and proto keyword
If a mux protocol is forced and an incompatible ALPN or NPN settings are
used, connection errors may be experienced. There is no check performed
during HAProxy startup and It is not necessarily obvious. So a note is added
to warn users about this usage.
2025-11-20 16:14:52 +01:00
Christopher Faulet
0a7f3954b5 BUG/MEDIUM: config: Use the mux protocol ALPN by default for listeners if forced
Since the commit 5003ac7fe ("MEDIUM: config: set useful ALPN defaults for
HTTPS and QUIC"), the ALPN is set by default to "h2,http/1.1" for HTTPS
listeners. However, it is in conflict with the forced mux protocol, if
any. Indeed, with "proto" keyword, the mux can be forced. In that case, some
combinations with the default ALPN will triggers connections errors.

For instance, by setting "proto h2", it will not be possible to use the H1
multiplexer. So we must take care to not advertise it in the ALPN. Worse,
since the commit above, most modern HTTP clients will try to use the H2
because it is advertised in the ALPN. By setting "proto h1" on the bind line
will make all the traffic rejected in error.

To fix the issue, and thanks to previous commits, if it is defined, we are
now relying on the ALPN defined by the mux protocol by default. The H1
multiplexer (only the one that can be forced) defines it to "http/1.1" while
the H2 multiplexer defines it to "h2". So by default, if one or another of
these muxes is forced, and if no ALPN is set, the mux ALPN is used.

Other multiplexers are not defining any default ALPN for now, because it is
useless. In addition, only the listeners are concerned because there is no
default ALPN on the server side.Finally, there is no tests performed if the
ALPN is forced on the bind line. It is the user responsibility to properly
configure his listeners (at least for now).

This patch depends on:
  * MINOR: config: Do proto detection for listeners before checks about ALPN
  * MINOR: muxes: Support an optional ALPN string when defining mux protocols

The series must be backported as far as 2.8.
2025-11-20 16:14:52 +01:00
Christopher Faulet
2ef8b91a00 MINOR: config: Do proto detection for listeners before checks about ALPN
The verification of any forced mux protocol, via the "proto" keyword, for
listeners is now performed before any tests on the ALPN. It will be
mandatory to be able to force the default ALPN, if not forced on the bind
line.

This patch will be mandatory for the next fix.
2025-11-20 16:14:52 +01:00
Christopher Faulet
8e08a635eb MINOR: muxes: Support an optional ALPN string when defining mux protocols
When a multiplexer protocol is defined, it is now possible to specify the
ALPN it supports, in binary format. This info is optionnal. For now only the
h2 and the h1 multiplexers define an ALPN because this will be mandatory for
a fix. But this could be used in future for different purpose.

This patch will be mandatory for the next fix.
2025-11-20 16:14:52 +01:00
Olivier Houchard
e9d34f991e BUG/MEDIUM: queues: Don't forget to unlock the queue before exiting
In assign_server_and_queue(), there's a rare case when the server was
full, so we created a pendconn, another server was considered but in the
meanwhile the pendconn was unqueued already, so we just left the
function. We did so, however, while still holding the queue lock, which
will ultimately lead to a deadlock, and ultimately the watchdog would
kill the process.
To fix that, just unlock the queue before leaving.

This should be backported to 3.2.
2025-11-20 13:57:06 +01:00
William Lallemand
1b443bdec5 DOC: acme: add details about key pair generation in ACME section
In 3.3 it is possible to generate a key pair without needing a
existing certificate on the disk.
2025-11-20 12:48:22 +01:00
William Lallemand
d6e3e5b3a6 DOC: acme: configuring acme needs a crt file
Configuring acme in 3.2 needs a certificate on the disk.

To be backported to 3.2
2025-11-20 12:44:54 +01:00
William Lallemand
332dcaecba DOC: acme: explain how to dump the certificates
The certificates can be dumped with either the dataplaneapi or the
haproxy-dump-certs scripts.

Must be backported in 3.2 as well as the script.
2025-11-20 12:40:38 +01:00
William Lallemand
5ff4c066e7 DOC: acme: add details about the DNS-01 support
DNS-01 is supported and was backported in 3.2.

Backport to 3.2.
2025-11-20 12:37:48 +01:00
William Lallemand
e0665d4ffe BUG/MINOR: acme: alert when the map doesn't exist at startup
When configuring an acme section with the 'map' keyword, the user must
use an existing map. If the map doesn't exist, a log will be emitted
when trying to add the challenge to the map.

This patch change the behavior by checking at startup if the map exists,
so haproxy would warn and won't start with a non-existing map.

This must be backported in 3.2.
2025-11-20 12:22:19 +01:00
Frederic Lecaille
fab7da0fd0 BUG/MEDIUM: quic-be/ssl_sock: TLS callback called without connection
Contrary to TCP, QUIC does not SSL_free() its SSL *  object when its ->close()
XPRT callback is called. This has as side effect to trigger some BUG_ON(!conn)
with <conn> the connection from TLS callbacks registered at configuration
parsing time, so after this <conn> have been released.

This is the case for instance with ssl_sock_srv_verifycbk() whose role is to
add some checks to the built-in server certificate verification process.

This patch prevents the pointer to <conn> dereferencing inside several callbacks
shared between TCP and QUIC.

Thank you to @InputOutputZ for its report in GH #3188.

As the QUIC backend feature arrived with the current 3.3 dev, no need to backport.
2025-11-20 11:36:57 +01:00
Willy Tarreau
8438ca273f MINOR: limits: explain a bit better what to do when fd limits are exceeded
As shown in github issue #3191, the error message shown when FD limits
are exceeded is not very useful as-is, since the current hard limit is
not displayed, and no suggestion is made about what to change in the
config. Let's explain about maxconn/ulimit-n/fd-hard-limit, suggest
dropping them or setting them to a context-based value at roughly 49%
of the current limit minus the known used FDs for listeners and checks.
This allows common "large" hard limits to report mostly round maxconns.
Example:

  [ALERT]    (25330) : [haproxy.main()] Cannot raise FD limit to 4001020,
  current limit is 1024 and hard limit is 4096. You may prefer to let
  HAProxy adjust the limit by itself; for this, please just drop any
  'maxconn' and 'ulimit-n' from the global section, and possibly add
  'fd-hard-limit' lower than this hard limit. You may also force a new
  'maxconn' value that is a bit lower than half of the hard limit minus
  listeners and checks. This results in roughly 1500 here.
2025-11-20 08:44:52 +01:00
Willy Tarreau
91d4f4f618 MINOR: limits: keep a copy of the rough estimate of needed FDs in global struct
It's always a pain to guess the number of FDs that can be needed by
listeners, checks, threads, pollers etc. We have this estimate in
global.maxsock before calling set_global_maxconn(), but we lose it
the line after. Let's copy it into global.est_fd_usage and keep it.
This will be helpful to try to provide more accurate suggestions for
maxconn.
2025-11-20 08:44:52 +01:00
Frederic Lecaille
2c6720a163 MINOR: quic: uneeded xprt context variable passed as parameter
This quic_conn ->xrpt_ctx is passed to qc_send_ppkts(), the quic_conn is retrieved
from this context to be used inside this function and it is not used at all
by this function.

This patch simply directly passes the quic_conn to qc_send_ppkts(). This is only
what this function needs.
2025-11-20 08:17:44 +01:00
Frederic Lecaille
a88fdf8669 MINOR: quic/flags: add missing QUIC flags for flags dev tool.
Add missing QUIC_FL_CONN_XPRT_CLOSED quic_conn flags definition.
2025-11-20 08:10:58 +01:00
Willy Tarreau
40687ebc64 REGTESTS: ssl: also verify that 0-rtt properly advertises early-data:1
This patch completes the 0-rtt test to verify that early-data:1 is
properly emitted to the server in the relevant situations. We carefully
compare it with the expected values that are computed based on the TLS
version, the client and listener's support for 0-rtt and the resumption
status. A response header "x-early-data-test" is set to OK on success,
or KO on failure and the client tests this. The previous test is kept
as well. This was tested with quictls-1.1.1 and quictls-3.0.1 for TCP,
as well as aws-lc for QUIC.
2025-11-19 22:30:31 +01:00
Willy Tarreau
2dc4d99cd2 REGTESTS: ssl: add basic 0rtt tests for TLSv1.2, TLSv1.3 and QUIC
These tests try all the combinations of {0,1}rtt <-> {0,1}rtt with
stateless and stateful tickets. They take into consideration the TLS
version to decide whether or not 0rtt should work. Since we cannot
use environment variables in the client, the tests are run in haproxy
itself where the frontends set a "x-early-rcvd-test" response header
that the client checks. At this stage, the test only verifies that
*some* early data were received.

Note that the tests are a bit complex because we need 4 listeners
for the various combinations of 0rtt/tickets, then we have to set
expectations based on the TLS version (1.2 vs 1.3), as well as the
session resumption status.

We have to set alpn on the server lines because currently our frontends
expect it for 0-rtt to work.
2025-11-19 22:30:21 +01:00
William Lallemand
f6373a6ca8 BUILD: Makefile: remove halog from install-admin
The dependency to halog build provokes problems when changing CFLAGS and
LDFLAGS, because you're suppose to have the same flags during the build
and the install if there's still some things to build.

We probably need to store the flags somewhere to reuse them at another
step, but we need to do it cleanly. In the meantime it's better not to
have this dependency.
2025-11-19 16:52:20 +01:00
Amaury Denoyelle
d54d78fe9a BUG/MINOR: quic: fix FD usage for quic_conn_closed on backend side
On the frontend side, QUIC transfer can be performed either via a
connection owned FD or multiplex on the listener one. When a quic_conn
is freed and converted to quic_conn_closed instance, its FD if open is
closed and all exchanges are now multiplex via the listener FD.

This is different for the backend as connections only has the choice to
use their owned FD. Thus, special care care must be taken when freeing a
connection and converting it to a quic_conn_closed instance. In this
case, qc_release_fd() is delayed to the quic_conn_closed release.

Furthermore, when the FD is transferred, its iocb and owner fields are
updated to the new quic_conn_closed instance. Without it, a crash will
occur when accessing the freed quic_conn tasklet. A newly dedicated
handler quic_conn_closed_sock_fd_iocb is used to ensure access to
quic_conn_closed members only.
2025-11-19 16:02:22 +01:00
Amaury Denoyelle
46c5c232d7 BUG/MINOR: quic: do not decrement jobs for backend conns
jobs is a global counter which serves to account activity through the
whole process. Soft-stop procedure will wait until this counter is
resetted to the nul value.

jobs is not used for backend connections. Thus, it is not incremented
when a QUIC backend connection is instantiated as expected. However,
decrement is performed on all sides during quic_conn_release(). This
causes the counter wrapping.

Fix this by decrementing jobs only for frontend connections. Without
this patch, soft stop procedure will hang indefinitely if QUIC backend
connections were in use.
2025-11-19 16:02:22 +01:00
Amaury Denoyelle
1a22caa6ed MINOR: quic: fix trace on quic_conn_closed release
Adjust leaving trace of quic_release_cc_conn() so that the end of the
function is properly reported.
2025-11-19 16:02:22 +01:00
Amaury Denoyelle
e55bcf5746 BUG/MINOR: mux-quic: implement max-reuse server parameter
Properly implement support for max-reuse server keyword. This is done by
adding a total count of streams seen for the whole connection. This
value is used in avail_streams callback.
2025-11-19 16:02:22 +01:00
William Lallemand
c8540f7437 BUG/MINOR: ssl: remove dead code in ssl_sock_from_buf()
When haproxy is compiled in -O0, the SSL_get_max_early_data() symbol is
used in the generated assembly, however -O2 seems to remove this symbol
when optimizing the code.

It happens because `if conn_is_back(conn)` and `if
(objt_listener(conn->target))` are opposed conditions, which mean we
never use the branch when objt_listener(conn->target) is true.

This patch removes the dead code. Bonus: SSL_get_max_early_data() is not
implemented in rustls, and that's the only thing preventing to start
with it.

This can be backported in every stable branches.
2025-11-19 11:00:05 +01:00
William Lallemand
1f562687e3 CI: github: make install-bin instead of make install
make install now have a dependency to install-admin which have a
dependency to admin/halog/halog.

halog links haproxy .o together with its own objects, but those objects
when built with ASAN must also be linked with ASAN or it won't be
possible to link the binary.

We don't need an ASAN-ready halog, so let's just do an install-bin
instead that will just install haproxy.
2025-11-18 20:11:23 +01:00
William Lallemand
c3a95ba839 BUILD: Makefile: make install with admin tools
`make install` now install some admin tools:

- halog in SBINDIR
- haproxy-dump-certs in SBINDIR
- haproxy-reload in SBINDIR
2025-11-18 20:02:24 +01:00
Willy Tarreau
14cb3799df REGTESTS: ssl: split the SSL reuse test into TLS 1.2/1.3
QUIC and TLS don't use the same tests because QUIC only supports
TLS 1.3 while SSL tests both TLS 1.2 and 1.3, which complicates
the tests scenarios.

This change extracts the core of the test into a single generic
ssl_reuse.vtci file and creates new high-level tests for TLSv1.2
over TCP, TLSv1.3 over TCP and TLSv1.3 over QUIC, which simply
include this file and set two variables. The test is now cleaner
and simpler.
2025-11-18 16:51:56 +01:00
William Lallemand
177816d2b8 BUG/MINOR: acme: P-256 doesn't work with openssl >= 3.0
When trying to use the P-256 curve in the acme configuration with
OpenSSL 3.x, the generation of the account was failing because OpenSSL
doesn't return a NIST or SECG curve name, but a ANSI X9.62 one.

Since the ANSI X9.62 curve names were not in the list, it couldn't match
anything supported.

This patch fixes the issue by adding both prime192v1 and prime256v1 name
in the struct curve array which is used during curve parsing.

Must be backported to 3.2.
2025-11-18 11:34:28 +01:00
William Lallemand
9bf01a0d29 BUG/MINOR: mworker: wrong signals during startup
Since the new master-worker model in 3.1, signals are registered in
step_init_3(). However, those signals were supposed to be registered
only for the worker or the standalone mode. It would call the wrong
callback in the master even during configuration parsing.

The patch set the signals handler to NULL for the master so it does
nothing until they really are registered.

Must be backported as far as 3.1.
2025-11-18 10:27:34 +01:00
William Lallemand
709cde6d08 BUG/MEDIUM: mworker: signals inconsistencies during startup and reload
Since haproxy 3.1, the master-worker mode changed to let the worker
parse the configuration instead of the master.

Previously, signals were blocked during configuration parsing and
unblocked before entering the polling loop of the master. This way it
was impossible to start a reload during the configuration parsing.

But with the new model, the polling loop is started in the master before
the configuration parsing is finished, and the signals are still
unblocked at this step. Meaning that it is possible to start a reload
while the configuration is parsing.

This patch reintroduce the behavior of blocking the signals during
configuration parsing adapted to the new model:

- Before the exec() of the reload, signals are blocked.
- When entering the polling loop, the SIGCHLD is unblocked because it is
  required to get a failure during configuration parsing in the worker
- Once the configuration is parsed, upon success in _send_status() or
  upon failure in run_master_in_recovery_mode() every signals are unblocked.

This patch must be backported as far as 3.1.
2025-11-18 10:05:42 +01:00
William Lallemand
b38405d156 CLEANUP: startup: move confusing msg variable
Move the char *msg variable declared in main() in a sub-block since
there's already multiple msg variable in other sub-blocks in this
function.

Also make it const.
2025-11-18 09:43:25 +01:00
Frederic Lecaille
37d01eea37 BUG/MEDIUM: quic-be: prevent use of MUX for 0-RTT sessions without secrets
The QUIC backend crashes when its peer does not support 0-RTT. In this case,
when the sessions are reused, no early-data level secrets are derived by
the TLS stack. This leads to crashes from qc_send_mux() which does not suppose
that both early-data level (qc->eel) and application level (qc->ael) cipher levels
could be non initialized.

To fix this:
  - prevent qc_send_mux() to send data if these two encryption level are not
    intialized. In this case it returns QUIC_TX_ERR_NONE;
  - avoid waking up the MUX from XPRT ->start() callback if the MUX is ready
    but without early-data level secrets to send them;
  - ensure the MUX is woken up by qc_ssl_do_handshake() after handshake completion
    if it is ready calling qc_notify_send()

Thank you to @InputOutputZ for having reported this issue in GH #3188.

No need to backport because QUIC backends is a current 3.3 development feature.
2025-11-17 15:40:24 +01:00
William Lallemand
0367227375 MEDIUM: mworker: set the mworker-max-reloads to 50
There was no mworker-max-reload value by default, it was set to INT_MAX
so this was impossible to reach.

The default value is now 50, which is still high, but no workers should
undergo that much reloads. Meaning that a worker will be killed with
SIGTERM if it reach this much reloads.
2025-11-17 11:54:30 +01:00
Amaury Denoyelle
c67a614e45 MINOR: quic: remove <ipv4> arg from qc_new_conn()
Remove <ipv4> argument from qc_new_conn(). This parameter is unnecessary
as it can be derived from the family type of the addresses also passed
as argument.
2025-11-17 10:20:54 +01:00
Amaury Denoyelle
133f100467 MINOR: quic: refactor qc_new_conn() prototype
The objective of this patch is to streamline qc_new_conn() usage so that
it is similar for frontend and backend sides.

Previously, several parameters were set only for frontend connections.
These arguments are replaced by a single quic_rx_packet argument, which
represents the INITIAL packet triggering the connection allocation on
the server side. For a QUIC client endpoint, it remains NULL. This usage
is consider more explicit.

As a minor change, <target> is moved as the first argument of the
function. This is considered useful as this argument determines whether
the connection is a frontend or backend entry.

Along with these changes, qc_new_conn() documentation has been reworded
so that it is now up-to-date with the newest usage.
2025-11-17 10:13:40 +01:00
Amaury Denoyelle
49edaca513 MINOR: quic: try to clarify quic_conn CIDs fields direction
quic_conn has two fields named <dcid> and <scid>. It may cause confusion
as it is not obvious how these fields are related to the connection
direction. Try to improve this by extending the documentation of these
two fields.
2025-11-17 10:11:04 +01:00
Amaury Denoyelle
035c026220 MINOR: quic: support multiple random CID generation for BE side
When a new backend connection is instantiated, a CID is first randomly
generated. It will serve as the first DCID for incoming packets from the
server. Prior to this patch, if the generated CID caused a collision
with an other entries from another connection, an error is reported and
the connection cannot be allocated.

This patch improves this procedure by implementing retries when a
collision occurs. Now, at most three attemps will be performed before
giving up. This is the same procedure already performed for CIDs
instantiated after RETIRE_CONNECTION_ID frame parsing.

Along with this functional change, qc_new_conn() is refactored for
backend instantiation. The CID generation is extracted from it and the
value is passed as an argument. This is considered cleaner as the code
is more similar between frontend and backend sides.
2025-11-17 10:11:04 +01:00
Amaury Denoyelle
8720130cc7 MINOR: quic: do not use quic_newcid_from_hash64 on BE side
quic_newcid_from_hash64 is an external callback. If defined, it serves
as a CID method generation, as an alternative to the default random
implementation.

This mechanism was not correctly implemented on the backend side.
Indeed, <hash64> quic_conn member is only setted for frontend
connections. The simplest solution would be to properly define it also
for backend ones. However, quic_newcid_from_hash64 derivation is really
only useful for the frontend side for now. Thus, this patch disables
using it on the backend side in favor of the default random generator.

To implement this, quic_cid_generate() is splitted in two functions, for
both methods of CIDs generation. This is the responsibility of the
caller to select the proper method. On backend side, only random
implementation is now used.
2025-11-17 10:11:04 +01:00
Christopher Faulet
fc6e3e9081 MINOR: stick-tables: Rename stksess shards to use buckets
The shard keyword is already used by the peers and on the server lines. And
it is unrelated with the session keys distribution. So instead of talking
about shard for the session key hashing, we now use the term "bucket".
2025-11-17 07:42:51 +01:00
Willy Tarreau
e5dadb2e8e [RELEASE] Released version 3.3-dev13
Released version 3.3-dev13 with the following main changes :
    - BUG/MEDIUM: config: for word expansion, empty or non-existing are the same
    - BUG/MINOR: quic: close connection on CID alloc failure
    - MINOR: quic: adjust CID conn tree alloc in qc_new_conn()
    - MINOR: quic: split CID alloc/generation function
    - BUG/MEDIUM: quic: handle collision on CID generation
    - MINOR: quic: extend traces on CID allocation
    - MEDIUM/OPTIM: quic: alloc quic_conn after CID collision check
    - MINOR: stats-proxy: ensure future-proof FN_AGE manipulation in me_generate_field()
    - BUG/MEDIUM: stats-file: fix shm-stats-file preload not working anymore
    - BUG/MINOR: do not account backend connections into maxconn
    - BUG/MEDIUM: init: 'devnullfd' not properly closed for master
    - BUG/MINOR: acme: more explicit error when BIO_new_file()
    - BUG/MEDIUM: quic-be: do not launch the connection migration process
    - MINOR: quic-be: Parse the NEW_TOKEN frame
    - MEDIUM: quic-be: Parse, store and reuse tokens provided by NEW_TOKEN
    - MINOR: quic-be: helper functions to save/restore transport params (0-RTT)
    - MINOR: quic-be: helper quic_reuse_srv_params() function to reuse server params (0-RTT)
    - MINOR: quic-be: Save the backend 0-RTT parameters
    - MEDIUM: quic-be: modify ssl_sock_srv_try_reuse_sess() to reuse backend sessions (0-RTT)
    - MINOR: quic-be: allow the preparation of 0-RTT packets
    - MINOR: quic-be: Send post handshake frames from list of frames (0-RTT)
    - MEDIUM: quic-be: qc_send_mux() adaptation for 0-RTT
    - MINOR: quic-be: discard the 0-RTT keys
    - MEDIUM: quic-be: enable the use of 0-RTT
    - MINOR: quic-be: validate the 0-RTT transport parameters
    - MINOR: quic-be: do not create the mux after handshake completion (for 0-RTT)
    - MINOR: quic-be: avoid a useless I/O callback wakeup for 0-RTT sessions
    - BUG/MEDIUM: acme: move from mt_list to a rwlock + ebmbtree
    - BUG/MINOR: acme: can't override the default resolver
    - MINOR: ssl/sample: expose ssl_*c_curve for AWS-LC
    - MINOR: check: delay MUX init when SSL ALPN is used
    - MINOR: cfgdiag: adjust diag on servers
    - BUG/MINOR: check: only try connection reuse for http-check rulesets
    - BUG/MINOR: check: fix reuse-pool if MUX inherited from server
    - MINOR: check: clarify check-reuse-pool interaction with reuse policy
    - DOC: configuration: add missing ssllib_name_startswith()
    - DOC: configuration: add missing openssl_version predicates
    - MINOR: cfgcond: add "awslc_api_atleast" and "awslc_api_before"
    - REGTESTS: ssl: activate ssl_curve_name.vtc for AWS-LC
    - BUILD: ech: fix clang warnings
    - BUG/MEDIUM: stick-tables: Always return the good stksess from stktable_set_entry
    - BUG/MINOR: stick-tables: Fix return value for __stksess_kill()
    - CLEANUP: stick-tables: Don't needlessly compute shard number in stksess_free()
    - MINOR: h1: h1_release() should return if it destroyed the connection
    - BUG/MEDIUM: h1: prevent a crash on HTTP/2 upgrade
    - MINOR: check: use auto SNI for QUIC checks
    - MINOR: check: ensure QUIC checks configuration coherency
    - CLEANUP: peers: remove an unneeded null check
    - Revert "BUG/MEDIUM: connections: permit to permanently remove an idle conn"
    - BUG/MEDIUM: connection: do not reinsert a purgeable conn in idle list
    - DEBUG: extend DEBUG_STRESS to ease testing and turn on extra checks
    - DEBUG: add BUG_ON_STRESS(): a BUG_ON() implemented only when DEBUG_STRESS > 0
    - DEBUG: servers: add a few checks for stress-testing idle conns
    - BUG/MINOR: check: fix QUIC check test when QUIC disabled
    - BUG/MINOR: quic-be: missing version negotiation
    - CLEANUP: quic: Missing succesful SSL handshake backend trace (OpenSSL 3.5)
    - BUG/MINOR: quic-be: backend SSL session reuse fix (OpenSSL 3.5)
    - REGTEST: quic: quic/ssl_reuse.vtc supports OpenSSL 3.5 QUIC API
2025-11-14 19:22:46 +01:00
Frederic Lecaille
d8f3ed6c23 REGTEST: quic: quic/ssl_reuse.vtc supports OpenSSL 3.5 QUIC API
This scripts is supported by OpenSSL 3.5 QUIC API since this previous commit:

   BUG/MINOR: quic: backend SSL session reuse fix (HAVE_OPENSSL_QUIC)

Should be backported where this commit is backported.
2025-11-14 18:06:47 +01:00
Frederic Lecaille
54eeda4b01 BUG/MINOR: quic-be: backend SSL session reuse fix (OpenSSL 3.5)
This bug impacts only the QUIC backends when haproxy is compiled against
OpenSSL 3.5 with QUIC API(HAVE_OPENSSL_QUIC).

The QUIC clients could not reuse their SSL session because the TLS tickets
received from the servers could not be provided to the TLS stack. This should
be done when the stack calls ha_quic_ossl_crypto_recv_rcd()
(OSSL_FUNC_SSL_QUIC_TLS_CRYPTO_RECV_RCD callback).

According to OpenSSL team, an SSL_read() call must be done after the handshake
completion. It seems the correct location is at the same level as for
SSL_process_quic_post_handshake() for quictls.

Thank you to @mattcaswell, @Sashan and @vdukhovni for having helped in solving
this issue.

Must be backported to 3.1
2025-11-14 17:50:49 +01:00
Frederic Lecaille
644bf585c3 CLEANUP: quic: Missing succesful SSL handshake backend trace (OpenSSL 3.5)
This very minor issue impacts only the backend when compiled against OpenSSL 3.5
with QUIC API (HAVE_OPENSSL_QUIC).

The "SSL handshake OK" trace was not dumped by a TRACE() call. This was very
annoying when debugging.

Modify the concerned code section which is a bit ugly and simplify it.
The TRACE() call is done at a unique location for now on.

Should be backported to 3.2 to ease any further backport.
2025-11-14 17:50:49 +01:00
Frederic Lecaille
f0c52f7160 BUG/MINOR: quic-be: missing version negotiation
This bug impacts only the QUIC clients (or backends). The version negotiation
was not supported at all for them. This is an oversight.

Contrary to the QUIC server which choose the negotiated version after having
received the transport parameters (into ClientHello message) the client selects
the negotiated version from the first Initial packet version field. Indeed, the
server transport parameters are inside the ServerHello messages ciphered
into Handshake packets.

This non intrusive patch does not impact the QUIC server implementation.
It only selects the negotiated version from the first Initial packet
received from the server and consequently initializes the TLS cipher context.

Thank you to @InputOutputZ for having reporte this issue in GH #3178.

No need to backport because the QUIC backends support arrives with 3.3.
2025-11-14 17:37:34 +01:00
Willy Tarreau
0746aa68b8 BUG/MINOR: check: fix QUIC check test when QUIC disabled
Latest commit ef206d441c ("MINOR: check: ensure QUIC checks configuration
coherency") introduced a regression when QUIC is not compiled in. Indeed,
not specifying a check proto sets mux_proto to NULL, which also happens to
be the value of get_mux_proto("QUIC"), so it complains about QUIC. Let's
add a non-null check in addition to this.

No backport is needed.
2025-11-14 17:27:53 +01:00
Willy Tarreau
4a6dec7193 DEBUG: servers: add a few checks for stress-testing idle conns
The latest idle conns fix 9481cef948 ("BUG/MEDIUM: connection: do not
reinsert a purgeable conn in idle list") addresses a very hard-to-hit
case which manifests itself with an attempt to reuse a connection fails
because conn->mux is NULL:

  Program terminated with signal SIGSEGV, Segmentation fault.
  #0  0x0000655410b8642c in conn_backend_get (reuse_mode=4, srv=srv@entry=0x6554378a7140,
      sess=sess@entry=0x7cfe140948a0, is_safe=is_safe@entry=0,
      hash=hash@entry=910818338996668161) at src/backend.c:1390
  1390     if (conn->mux->takeover && conn->mux->takeover(conn, i, 0) == 0) {

However the condition that leads to this situation can be detected
earlier, by the presence of the connection in the toremove_list, whose
race window is much larger and easier to detect.

This patch adds a few BUG_ON_STRESS() at selected places that an detect
this condition. When built with -DDEBUG_STRESS and run under stress with
two distinct processes communicating over H2 over SSL, under a stress of
400-500k req/s, the front process usually crashes in the first 10-30s
triggering in _srv_add_idle() if the fix above is reverted (and it does
not crash with the fix).

This is mainly included to serve as an illustration of how to instrument
the code for seamless stress testing.
2025-11-14 17:00:17 +01:00
Willy Tarreau
675c86c4aa DEBUG: add BUG_ON_STRESS(): a BUG_ON() implemented only when DEBUG_STRESS > 0
The purpose of this new BUG_ON is beyond BUG_ON_HOT(). While BUG_ON_HOT()
is meant to be light but placed on very hot code paths, BUG_ON_STRESS()
might be heavy and only used under stress-testing, to try to detect early
that something bad is starting to happen. This one is not even type-checked
when not defined because we don't want to risk the compiler emitting the
slightest piece of code there in production mode, so as to give enough
freedom to the developers.
2025-11-14 16:42:53 +01:00
Willy Tarreau
3d441e78e5 DEBUG: extend DEBUG_STRESS to ease testing and turn on extra checks
DEBUG_STRESS is currently used only to expose "stress-level". With this
patch, we go a bit further, by automatically forcing DEBUG_STRICT and
DEBUG_STRICT_ACTION to their highest values in order to enable all
BUG_ON levels, and make all of them result in a crash. In addition,
care is taken to always only have 0 or 1 in the macro, so that it can be
tested using "#if DEBUG_STRESS > 0" as well as "if (DEBUG_STRESS) { }"
everywhere.

The goal will be to ease insertion of extra tests for builds dedicated
to stress-testing that enable possibly expensive extra checks on certain
code paths that cannot reasonably be compiled in for production code
right now.
2025-11-14 16:38:04 +01:00
Amaury Denoyelle
9481cef948 BUG/MEDIUM: connection: do not reinsert a purgeable conn in idle list
A recent patch was introduced to fix a rare race condition in idle
connection code which would result in a crash. The issue is when MUX IO
handler run on top of connection moved in the purgeable list. The
connection would be considered as present in the idle list instead, and
reinserted in it at the end of the handler while still in the purge
list.

  096999ee208b8ae306983bc3fd677517d05948d2
  BUG/MEDIUM: connections: permit to permanently remove an idle conn

This patch solves the described issue. However, it introduces another
bug as it may clear connection flag when removing a connection from its
parent list. However, these flags now serve primarily as a status which
indicate that the connection is accounted by the server. When a backend
connection is freed, server idle/used counters are decremented
accordingly to these flags. With the above patch, an incorrect counter
could be adjusted and thus wrapping would occured.

The first impact of this bug is that it may distort the estimated number
of connections needed by servers, which would result either in poor
reuse rate or too many idle connections kept. Another noticeable impact
is that it may prevent server deletion.

The main problem of the original and current issues is that connection
flags are misinterpreted as telling if a connection is present in the
idle list. As already described here, in fact these flags are solely a
status which indicate that the connection is accounted in server
counters. Thus, here are the definitive conclusion that can be learned
here :

* (conn->flags & CO_FL_LIST_MASK) == 1:
  the connection is accounted by the server
  it may or may not be present in the idle list

* (conn->flags & CO_FL_LIST_MASK) == 0
  the connection is not accounted and not present in idle list

The discussion above does not mention session list, but a similar
pattern can be observed when CO_FL_SESS_IDLE flag is set.

To keep the original issue solved and fix the current one, IO MUX
handlers prologue are rewritten. Now, flags are not checked anymore for
list appartenance and LIST_INLIST macro is used instead. This is
definitely clearer with conn_in_list purpose here.

On IO MUX handlers end, conn idle flags may be checked if conn_in_list
was true, to reinsert the connection either in idle or safe list. This
is considered safe as no function should modify idle flags when a
connection is not stored in a list, except during conn_free() operation.

This patch must be backported to every stable versions after revert of
the above commit. It should be appliable up to 3.0 without any issue. On
2.8 and below, <idle_list> connection member does not exist. It should
be safe to check <leaf_p> tree node as a replacement.
2025-11-14 16:06:34 +01:00
Amaury Denoyelle
d79295d89b Revert "BUG/MEDIUM: connections: permit to permanently remove an idle conn"
The target patch fixes a rare race condition which happen when a MUX IO
handler is working on a connection already moved into the purge list. In
this case, the handler will incorrectly moved back the connection into
the idle list.

To fix this, conn_delete_from_tree() was extended to remove flags along
with the connection from the idle list. This was performed when the
connection is moved into the purge list. However, it introduces another
issue related to the idle server connection accounting. Thus it is
necessary to revert it prior to the incoming newer fix.

This patch must be backported to every version where the original commit
is.
2025-11-14 16:06:34 +01:00
Willy Tarreau
6b9c3d0621 CLEANUP: peers: remove an unneeded null check
Coverity reported in GH #3181 that a NULL test was useless, in
peers_trace(), which is true since the peer always belongs to a
peers section and it was already dereferenced. Let's just remove
the test to avoid the confusion.
2025-11-14 13:47:20 +01:00
Amaury Denoyelle
ef206d441c MINOR: check: ensure QUIC checks configuration coherency
QUIC is now supported on the backend side, thus it is possible to use it
with server checks. However, checks configuration can be quite
extensive, differing greatly from the server settings.

This patch ensures that QUIC checks are always performed under a
controlled context. Objectives are to avoid any crashes and ensure that
there is no suprise for users in respect to the configuration.

The first part of this patch ensures that QUIC checks can only be
activated on QUIC servers. Indeed, QUIC requires dedicated
initialization steps prior to its usage.

The other part of this patch disables QUIC usage when one or multiple
specific check connection settings are specified in the configuration,
diverging from the server settings. This is the simplest solution for
now and ensure that there is no hidden behavior to users. This means
that it's currently impossible to perform QUIC checks if other endpoints
that the server itself. However for now there is no real use-case for
this scenario.

Along with these changes, check-proto documentation is updated to
clarify QUIC checks behavior.
2025-11-14 13:42:08 +01:00
Amaury Denoyelle
ca5a5f37a1 MINOR: check: use auto SNI for QUIC checks
By default, check SNI is set to the Host header when an HTTPS check is
performed. This patch extends this mode so that it is also active when
QUIC checks are executed.

This patch should improve reuse rate with checks. Indeed, SNI is also
already automatically set for normal traffic. The same value must be
used during check so that a connection hash match can be found.
2025-11-14 13:42:08 +01:00
Olivier Houchard
333deef485 BUG/MEDIUM: h1: prevent a crash on HTTP/2 upgrade
Change h1_process() to return -2 when the mux is destroyed but the
connection is not, so that we can differentiate between "both mux and
connection were destroyed" and "only the mux was destroyed".
It can happen that only the mux gets destroyed, and the connection is
still alive, if we did upgrade it to HTTP/2.
In h1_wake(), if the connection is alive, then return 0, as the wake
methods should only return -1 if the connection is dead.
This fixes a bug where the ssl xprt would consider the connection
destroyed, and thus would consider its tasklet should die, and return
NULL, and its TASK_RUNNING flag would never be removed, leading to an
infinite loop later on. This would happen anytime an HTTP/2 upgrade was
successful.

This should be backported up to 2.8. While the bug by commit
00f43b7c8b136515653bcb2fc014b0832ec32d61, it was not triggered before
only by chance, and exists in previous releases too.
2025-11-14 12:49:35 +01:00
Olivier Houchard
2f8f09854f MINOR: h1: h1_release() should return if it destroyed the connection
h1_release() is called to destroy everything related to the mux h1,
usually even the connection. However, it handles upgrades to HTTP/2 too,
in which case the h1 mux will be destroyed, but the connection will
still be alive. So make it so it returns 0 if everything is destroyed,
and -1 if the connection is still alive.

This should be backported up to 2.8, as a future bugfix will depend on
it.
2025-11-14 12:49:35 +01:00
Christopher Faulet
14a333c4f4 CLEANUP: stick-tables: Don't needlessly compute shard number in stksess_free()
Since commit 0bda33a3e ("MINOR: stick-tables: remove the uneeded read lock
in stksess_free()"), the lock on the shard is no longer acquired. So it is
useless to still compture the shard number. The result is never used and can
be safely removed.
2025-11-14 11:56:14 +01:00
Christopher Faulet
346d6c3ac7 BUG/MINOR: stick-tables: Fix return value for __stksess_kill()
The commit 9938fb9c7 ("BUG/MEDIUM: stick-tables: Fix race with peers when
killing a sticky session") introduced a regression.

__stksess_kill() must always return 0 if the session cannot be released. But
when the ref_cnt is tested under the update lock, a success is reported if
the session is still in-used. 0 must be returned in that case.

This bug is harmless because callers never use the return value of
__stksess_kill() or stksess_kill().

This bug must be backported as far as 3.0.
2025-11-14 11:56:14 +01:00
Christopher Faulet
bd4fff9a76 BUG/MEDIUM: stick-tables: Always return the good stksess from stktable_set_entry
In stktable_set_entry(), the return value of __stktable_store() is not
tested while it is possible to get an existing session with the same key
instead of the one we want to insert. It happens when we fails to upgrade
the read lock on the bucket to an write lock. In that case, we release the
lock for a short time to get a write lock.

So, to fix the bug, we must check the session returned by __stktable_store()
and take care to return this one.

The bug was introduced by the commit e62885237c ("MEDIUM: stick-table: make
stktable_set_entry() look up under a read lock"). It must be backported as
far as 2.8.
2025-11-14 11:56:12 +01:00
William Lallemand
bf639e581d BUILD: ech: fix clang warnings
No impact as the state is either SHOW_ECH_SPECIFIC or SHOW_ECH_ALL but
never anything else.

src/ech.c:240:6: error: variable 'p' is used uninitialized whenever 'if' condition is false [-Werror,-Wsometimes-uninitialized]
  240 |         if (ctx->state == SHOW_ECH_ALL) {
      |             ^~~~~~~~~~~~~~~~~~~~~~~~~~
src/ech.c:275:12: note: uninitialized use occurs here
  275 |         ctx->pp = p;
      |                   ^
src/ech.c:240:2: note: remove the 'if' if its condition is always true
  240 |         if (ctx->state == SHOW_ECH_ALL) {
      |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/ech.c:228:17: note: initialize the variable 'p' to silence this warning
  228 |         struct proxy *p;
      |                        ^
      |                         = NULL
src/ech.c:240:6: error: variable 'bind_conf' is used uninitialized whenever 'if' condition is false [-Werror,-Wsometimes-uninitialized]
  240 |         if (ctx->state == SHOW_ECH_ALL) {
      |             ^~~~~~~~~~~~~~~~~~~~~~~~~~
src/ech.c:276:11: note: uninitialized use occurs here
  276 |         ctx->b = bind_conf;
      |                  ^~~~~~~~~
src/ech.c:240:2: note: remove the 'if' if its condition is always true
  240 |         if (ctx->state == SHOW_ECH_ALL) {
      |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/ech.c:229:29: note: initialize the variable 'bind_conf' to silence this warning
  229 |         struct bind_conf *bind_conf;
      |                                    ^
      |                                     = NULL
2 errors generated.
make: *** [Makefile:1062: src/ech.o] Error 1
2025-11-14 11:35:38 +01:00
William Lallemand
e17881128b REGTESTS: ssl: activate ssl_curve_name.vtc for AWS-LC
It was difficult to test ssl_curve_name.vtc with AWS-LC without a way to
check the AWS-LC API. Let's add awslc_api_atleast() in the start
conditions.
2025-11-14 11:01:45 +01:00
William Lallemand
3d15c07ed0 MINOR: cfgcond: add "awslc_api_atleast" and "awslc_api_before"
AWS-LC features are not easily tested with just the openssl version
constant. AWS-LC uses its own API versioning stored in the
AWSLC_API_VERSION constant.

This patch add the two awslc_api_atleast and awslc_api_before predicates
that help to check the AWS-LC API.
2025-11-14 11:01:45 +01:00
William Lallemand
35d21a8bc0 DOC: configuration: add missing openssl_version predicates
Add missing openssl_version_atleast() and  openssl_version_before()
predicates.

The predicates exist since 3aeb3f9347 ("MINOR: cfgcond: implements
openssl_version_atleast and openssl_version_before").

Must be backported in every stable versions.
2025-11-14 11:01:45 +01:00
William Lallemand
9ad018a3dd DOC: configuration: add missing ssllib_name_startswith()
Add the missing ssllib_name_startswith() predicate in the documentation.

The predicate was introduced with b01179aa9 ("MINOR: ssl: Add
ssllib_name_startswith precondition").

Must be backported as far as 2.6.
2025-11-14 11:01:45 +01:00
Amaury Denoyelle
8415254cea MINOR: check: clarify check-reuse-pool interaction with reuse policy
check-reuse-pool can only perform as expected if reuse policy on the
backend is set to aggressive or higher. Update the documentation to
reflect this and implement a server diag warning.
2025-11-14 10:44:05 +01:00
Amaury Denoyelle
52a7d4ec39 BUG/MINOR: check: fix reuse-pool if MUX inherited from server
Check reuse is only performed if no specific check connect options are
specified on the configuration. This ensures that reuse won't be
performed if intending to use different connection parameters from the
default traffic.

This relies on tcpcheck_use_nondefault_connect() which indicates if the
check has any specific connection parameters. One of them if check
<mux_proto> field. However, this field may be automatically set during
init_srv_check() in some specific conditions without any explicit
configuration, most notably when using http-check rulesets on an HTTP
backend. Thus, it prevents connection reuse for these checks.

This commit fixes this by adjuting tcpcheck_use_nondefault_connect().
Beside checking check <mux_proto> field, it also detects if it is
different from the server configuration. This is sufficient to know if
the value is derived from the configuration or automatically calculated
in init_srv_check().

Note that this patch introduces a small behavior change. Prior to it,
check reuse were never performed if "check-proto" is explicitely
configured. Now, check reuse will be performed if the configured value
is identical to the server MUX protocol. This is considered as
acceptable as connection reuse is safe when using a similar MUX
protocol.

This must be backported up to 3.2.
2025-11-14 10:44:05 +01:00
Amaury Denoyelle
5d021c028e BUG/MINOR: check: only try connection reuse for http-check rulesets
In 3.2, a new server keyword "check-reuse-pool" has been introduced. It
allows to reuse a connection for a new check, instead of always
initializing a new one. This is only performed if the check does not
rely on specific connection parameters differing from the server.

This patch further restricts reuse for checks only when an HTTP ruleset
is used at the backend level. Indeed, reusing a connection outside of
HTTP is an undefined behavior. The impact of this bug is unknown and
depends on the proxy/server configuration. In the case of an HTTP
backend with non-HTTP checks, check-reuse-pool would probably cause a
drop in reuse rate.

Along this change, implement a new diagnostic warning on servers to
report that check-reuse-pool cannot apply due to an incompatible check
type.

This must be backported up to 3.2.
2025-11-14 10:44:03 +01:00
Amaury Denoyelle
d92f8f84fb MINOR: cfgdiag: adjust diag on servers
Adjust code dealing with diagnostics performed on server. The objective
is to extract the check on duplicate cookies in a dedicated function
outside of the proxies/servers loop.

This does not have any noticeable impact. This patch is merely a code
improvment to implement easily new future diagnostics on servers.
2025-11-14 10:00:26 +01:00
Amaury Denoyelle
d12971dfea MINOR: check: delay MUX init when SSL ALPN is used
When instantiating a new connection for check, its MUX may be
initialized early. This was not performed though if SSL ALPN negotiation
will be used, except if check MUX is already fixed.

However, this method of initialization is problematic when QUIC MUX is
used. Indeed, this multiplexer must only be instantiated after the above
application protocol is known, which is derived from the ALPN
negotiation. If this is not the case a crash will occur in qmux_init().

In fact, a similar problem was already encountered for normal traffic.
Thus, a change was performed in connect_server() : MUX early
initialization is now always skipped if SSL ALPN negotiation is active,
even if MUX is already fixed. This patch introduces a similar change for
checks.

Without this patch, it is not possible to perform check on QUIC servers
as expected. Indeed, when http-check ruleset is active a crash would
occur prior to it.
2025-11-14 09:49:04 +01:00
Damien Claisse
1d46c08689 MINOR: ssl/sample: expose ssl_*c_curve for AWS-LC
The underlying SSL_get_negotiated_group function has been backported
into AWS-LC [1], so expose the feature for users of this TLS stack
as well. Note that even though it was actually added in AWS-LC 1.56.0,
we require AWSLC_API_VERSION >= 35 which was released in AWS-LC 1.57.0,
because API version wasn't incremented after this change. As the delta
is one minor version (less than two weeks), I consider this acceptable
to avoid relying on a proxy constant like TLSEXT_nid_unknown which
might be removed at some point.

[1] d6a37244ad
2025-11-13 17:36:43 +01:00
William Lallemand
b9b158ea4c BUG/MINOR: acme: can't override the default resolver
httpclient_acme_init() was called in cfg_parse_acme() which is at
section parsing. httpclient_acme_init() also calls
httpclient_create_proxy() which could create a "default" resolvers
section if it doesn't exists.

If one tries to override the default resolvers section after an ACME
section, the resolvers section parsing will fail because the section was
already created by httpclient_create_proxy().

This patch fixes the issue by moving the initialization of the ACME
proxy to a pre_check callback, which is called just before
check_config_validity().

Must be backported in 3.2.
2025-11-13 17:17:11 +01:00
William Lallemand
2bdf5a7937 BUG/MEDIUM: acme: move from mt_list to a rwlock + ebmbtree
The current ACME scheduler suffers from problems due to the way the
tasks are stored:

- MT_LIST are not scalables when having a lot of ACME tasks and having
  to look for a specific one.
- the acme_task pointer was stored in the ckch_store in order to not
  passing through the whole list. But a ckch_store can be updated and
  the pointer lost in the previous one.
- when a task fails, the ptr in the ckch_store was not removed because
  we only work with a copy of the original ckch_store, it would need to
  lock the ckchs_tree and remove this pointer.

This patch fixes the issues by removing the MT_LIST-based architecture,
and replacing it by a simple ebmbtree + rwlock design.

The pointer to the task is not stored anymore in the ckch_store, but
instead it is stored in the acme_tasks tree. Finding a task is done by
doing a lookup on this tree with a RDLOCK.
Instead of checking if store->acme_task is not NULL, a lookup is also
done.

This allow to remove the stuck "acme_task" pointer in the store, which
was preventing to restart an acme task when the previous failed for this
specific certificate.

Must be backported in 3.2.
2025-11-13 15:18:12 +01:00
Frederic Lecaille
c76e072e43 MINOR: quic-be: avoid a useless I/O callback wakeup for 0-RTT sessions
For backends and 0-RTT sessions, this patch modifies the ->start() callback to
wake up the I/O callback only if the connection (and the mux) is not ready. Note that
connect_server() has been modified to call this xprt callback just after having
created the mux and installed the mux. Contrary to 1-RTT session, for 0-RTT sessions,
the connections are always ready before calling this ->start xprt callback.
2025-11-13 14:04:31 +01:00
Frederic Lecaille
92d2ab76e0 MINOR: quic-be: do not create the mux after handshake completion (for 0-RTT)
This is required during connection with 0-RTT support, to prevent two mux creations.
Indeed, for 0-RTT sessions, the QUIC mux is already started very soon from
connect_server() (src/backend.c).
2025-11-13 14:04:31 +01:00
Frederic Lecaille
d84463f9f6 MINOR: quic-be: validate the 0-RTT transport parameters
During 0-RTT sessions, some server transport parameters are reused after having
been save from previous sessions. These parameters must not be reduced
when it resends them. The client must check this is the case when some early data
are accepted by the server. This is what is implemented by this patch.

Implement qc_early_tranport_params_validate() which checks the new server parameters
are not reduced.

Also implement qc_ssl_eary_data_accepted() which was not implemented for TLS
stack without 0-RTT support (for instance wolfssl). That said this function
was no more used. This is why the compilation against wolfssl could not fail.
2025-11-13 14:04:31 +01:00
Frederic Lecaille
6419b9f204 MEDIUM: quic-be: enable the use of 0-RTT
This patch allows the use of 0-RTT feature on QUIC server lines with "allow-0rtt"
option. In fact 0-RTT is really enabled only if ssl_sock_srv_try_reuse_sess()
successfully manages to reuse the SSL session and the chosen application protocol
from previous connections.

Note that, at this time, 0-RTT works only with quictls and aws-lc as TLS stack.

(0-RTT does not work at all (even for QUIC frontends) with libressl).
2025-11-13 14:04:31 +01:00
Frederic Lecaille
46d490f7c2 MINOR: quic-be: discard the 0-RTT keys
This patch allows the discarding of the 0-RTT keys as soon as 1-RTT keys
are available.
2025-11-13 14:04:31 +01:00
Frederic Lecaille
3f60891360 MEDIUM: quic-be: qc_send_mux() adaptation for 0-RTT
When entering this function, a selection is done about the encryption level
to be used to send data. For a client, the early data encryption level
is used to send 0-RTT if this encryption level is initialized.

The Initial encryption is also registered to the send list for clients if there
is Initial crypto data to send. This allow Initial and 0-RTT packets to
be coalesced by datagrams.
2025-11-13 14:04:31 +01:00
Frederic Lecaille
a4bbbc75db MINOR: quic-be: Send post handshake frames from list of frames (0-RTT)
This patch is required to make 0-RTT work. It modifies the prototype of
quic_build_post_handshake_frames() to send post handshake frames from a
list of frames in place of the application encryption level (used
as <qc->ael> local variable).

This patch does not modify at all the current QUIC stack behavior (even for
QUIC frontends). It must be considered as a preparation for the code
to come about 0-RTT support for QUIC backends.
2025-11-13 14:04:31 +01:00
Frederic Lecaille
ac1d3eba88 MINOR: quic-be: allow the preparation of 0-RTT packets
A QUIC server never sends 0-RTT packets contrary to the client.

This very simple modification allow the the preparation of 0-RTT packets
with early data as encryption level (->eel).
2025-11-13 14:04:31 +01:00
Frederic Lecaille
6e14365a5b MEDIUM: quic-be: modify ssl_sock_srv_try_reuse_sess() to reuse backend sessions (0-RTT)
This function is called for both TCP and QUIC connections to reuse SSL sessions
saved by ssl_sess_new_srv_cb() callback called upon new SSL session creation.

In addition to this, a QUIC SSL session must reuse the ALPN and some specific QUIC
transport parameters. This is what is added by this patch for QUIC 0-RTT sessions.

Note that for now on, ssl_sock_srv_try_reuse_sess() may fail for QUIC connections
if it did not managed to reuse the ALPN. The caller must be informed of such an
issue. It must not enable 0-RTT for the current session in this case. This is
impossible without ALPN which is required to start a mux.

ssl_sock_srv_try_reuse_sess() is modified to always succeeds for TCP connections.
2025-11-13 14:04:31 +01:00
Frederic Lecaille
5309dfb56b MINOR: quic-be: Save the backend 0-RTT parameters
For both TCP and QUIC connections, this is ssl_sess_new_srv_cb() callback which
is called when a new SSL session is created. Its role is to save the session to
be reused for the next sessions.

This patch modifies this callback to save the QUIC parameters to be reused
for the next 0-RTT sessions (or during SSL session resumption).

The already existing path_params->nego_alpn member is used to store the ALPN as
this is done for TCP alongside path_params->tps new quic_early_transport_params
struct used to save the QUIC transport parameters to be reused for 0-RTT sessions.
2025-11-13 14:04:31 +01:00
Frederic Lecaille
41e40eb431 MINOR: quic-be: helper quic_reuse_srv_params() function to reuse server params (0-RTT)
Implement quic_reuse_srv_params() whose role is to reuse the ALPN negotiated
during a first connection to a QUIC backend alongside its transport parameters.
2025-11-13 14:04:31 +01:00
Frederic Lecaille
33564ca54c MINOR: quic-be: helper functions to save/restore transport params (0-RTT)
Define quic_early_transport_params new struct for QUIC transport parameters
in relation with 0-RTT. This parameters must be saved during a first session to
be reused for 0-RTT next sessions.

qc_early_transport_params_cpy() copies the 0-RTT transport parameters to be
saved during a first connection to a backend. The copy is made from
a quic_transport_params struct to a quic_ealy_transport_params struct.

On the contrary, qc_early_transport_params_reuse() copies the transport parameters
to be reused for a 0-RTT session from a previous one. The copy is made
from a quic_early_transport_params strcut to a quic_transport_params struct.

Also add QUIC_EV_EARLY_TRANSP_PARAMS trace event to dump such 0-RTT
transport parameters from traces.
2025-11-13 14:04:31 +01:00
Frederic Lecaille
80070fe51c MEDIUM: quic-be: Parse, store and reuse tokens provided by NEW_TOKEN
Add a per thread ist struct to srv_per_thread struct to store the QUIC token to
be reused for subsequent sessions.

Parse at packet level (from qc_parse_ptk_frms()) these tokens and store
them calling qc_try_store_new_token() newly implemented function. This is
this new function which does its best (may fail) to update the tokens.

Modify qc_do_build_pkt() to resend these tokens calling quic_enc_token()
implemented by this patch.
2025-11-13 14:04:31 +01:00
Frederic Lecaille
8f23d4d287 MINOR: quic-be: Parse the NEW_TOKEN frame
Rename ->data qf_new_token struct field to ->w_data to distinguish it from
->r_data new field used to parse the NEW_TOKEN frame. Indeed to build the
NEW_TOKEN we need to write it to a static buffer into the frame struct. To
parse it we only need to store the address of the token field into the
RX buffer.
2025-11-13 14:04:31 +01:00
Frederic Lecaille
64e32a0767 BUG/MEDIUM: quic-be: do not launch the connection migration process
At this time the connection migration is not supported by QUIC backends.
This patch prevents this process to be launched for connections to QUIC backends.

Furthermore, the connection migration process could be started systematically
when connecting a backend to INADDR_ANY, leading to crashes into qc_handle_conn_migration()
(when referencing qc->li).

Thank you to @InputOutputZ for having reported this issue in GH #3178.

This patch simply checks the connection type (listener or not) before checking if
a connection migration must be started.

No need to backport because support for QUIC backends is available from 3.3.
2025-11-13 13:52:40 +01:00
William Lallemand
071e5063d8 BUG/MINOR: acme: more explicit error when BIO_new_file()
Replace the error message of BIO_new_file() when the account-key cannot
be created on disk by "acme: cannot create the file '%s'". It was
previously "acme: out of memory." Which is unclear.

Must be backported to 3.2.
2025-11-13 11:56:33 +01:00
Remi Tricot-Le Breton
1b19e4ef32 BUG/MEDIUM: init: 'devnullfd' not properly closed for master
Since commit "1ec59d3 MINOR: init: Make devnullfd global and create it
earlier in init" the devnullfd pointing towards /dev/null gets created
early in the init process but it was closed after the call to
"mworker_run_master". The master process never got to the FD closing
code and we had an FD leak.

This patch does not need to be backported.
2025-11-12 16:06:28 +01:00
Amaury Denoyelle
7927ee95f3 BUG/MINOR: do not account backend connections into maxconn
Remove QUIC backend connections from global actconn accounting. Indeed,
this counter is only used on the frontend side. This is required to
ensure maxconn coherence.
2025-11-12 14:45:00 +01:00
Aurelien DARRAGON
3262da84ea BUG/MEDIUM: stats-file: fix shm-stats-file preload not working anymore
Due to recent commit 5c299dee ("MEDIUM: stats: consider that shared stats
pointers may be NULL") shm-stats-file preloading suddenly stopped working

In fact preloading should be considered as an initializing step so the
counters may be assigned there without checking for NULL first.
Indeed there are supposed to be NULL because preloading occurs before
counters_{fe,be}_shared_prepare() which takes care of setting the pointers
for counters if they weren't set before.

Obviously this corner-case was overlooked during 5c299dee writing and
testing. Thanks to Nick Ramirez for having reported the issue.

No backport needed, this issue is specific to 3.3.
2025-11-11 22:36:17 +01:00
Aurelien DARRAGON
a287841578 MINOR: stats-proxy: ensure future-proof FN_AGE manipulation in me_generate_field()
Commit ad1bdc33 ("BUG/MAJOR: stats-file: fix crash on non-x86 platform
caused by unaligned cast") revealed an ambiguity in me_generate_field()
around FN_AGE manipulation. For now FN_AGE can only be stored as u32 or
s32, but in the future we could also support 64bit FN_AGES, and the
current code assumes 32bits types and performs and explicit unsigned int
cast. Instead we group current 32 bits operations for FF_U32 and FF_S32
formats, and let room for potential future formats for FN_AGE.

Commit ad1bdc33 also suggested that the fix was temporary and the approach
must change, but after a code review it turns out the current approach
(generic types manipulation under me_generate_field()) is legit. The
introduction of shm-stats-file feature didn't change the logic which
was initially implemented in 3.0. It only extended it and since shared
stats are now spread over thread-groups since 3.3, the use of atomic
operations made typecasting errors more visible, and structure mapping
change from d655ed5f14 ("BUG/MAJOR: stats-file: ensure
shm_stats_file_object struct mapping consistency (2nd attempt)") was in
fact the only change to blame for the crash on non-x86 platforms.

With ambiguities removed in me_generate_field(), let's hope we don't face
similar bugs in the future. Indeed, with generic counters, and more
specifically shared ones (which leverage atomic ops), great care must be
taken when changing their underlying types as me_generate_field() solely
relies on stat_col descriptor to know how to read the stat from a generic
pointer, so any breaking change must be reflected in that function as well

No backport needed.
2025-11-10 21:32:22 +01:00
Amaury Denoyelle
5a8728d03a MEDIUM/OPTIM: quic: alloc quic_conn after CID collision check
On Initial packet parsing, a new quic_conn instance is allocated via
qc_new_conn(). Then a CID is allocated with its value derivated from
client ODCID. On CID tree insert, a collision can occur if another
thread was already parsing an Initial packet from the same client. In
this case, the connection is released and the packet will be requeued to
the other thread.

Originally, CID collision check was performed prior to quic_conn
allocation. This was changed by the commit below, as this could cause
issue on quic_conn alloc failure.

  commit 4ae29be18c5b212dd2a1a8e9fa0ee2fcb9dbb4b3
  BUG/MINOR: quic: Possible endless loop in quic_lstnr_dghdlr()

However, this procedure is less optimal. Indeed, qc_new_conn() performs
many steps, thus it could be better to skip it on Initial CID collision,
which can happen frequently. This patch restores the older order of
operations, with CID collision check prior to quic_conn allocation.

To ensure this does not cause again the same bug, the CID is removed in
case of quic_conn alloc failure. This should prevent any loop as it
ensures that a CID found in the global tree does not point to a NULL
quic_conn, unless if CID is attach to a foreign thread. When this thread
will parse a re-enqueued packet, either the quic_conn is already
allocated or the CID has been removed, triggering a fresh CID and
quic_conn allocation procedure.
2025-11-10 12:10:14 +01:00
Amaury Denoyelle
a9d11ab7f3 MINOR: quic: extend traces on CID allocation
Add new traces to detect the CID generation method and also when an
Initial packet is requeued due to CID collision.
2025-11-10 12:10:14 +01:00
Amaury Denoyelle
2623e0a0b7 BUG/MEDIUM: quic: handle collision on CID generation
CIDs are provided by haproxy so that the peer can use them as DCID of
its packets. Their value is set via a random generator. It happens on
several occasions during connection lifetime:
* via ODCID derivation if haproxy is the server
* on quic_conn init if haproxy is the client
* during post-handshake if haproxy is the server
* on RETIRE_CONNECTION_ID frame parsing

CIDs are stored in a global tree. On ODCID derivation, a check is
performed to ensure the CID is not a duplicate value. This is mandatory
to properly handle multiple INITIAL packets from the same client on
different thread.

However, for the other cases, no check is performed for CID collision.
As _quic_cid_insert() is silent, the issue is not detected at all. This
results in a CID advertized to the peer but not stored in the global
one. In the end, this may cause two issues. The first one is that
packets from the client which use the new CID will be rejected by
haproxy, most probably with a STATELESS_RESET. The second issue is that
it can cause a crash during quic_conn release. Indeed, the CID is stored
in the quic_conn local tree and thus eb_delete() for the global tree
will be performed. As <leaf_p> member is uninit, this results in a
segfault.

Note that this issue is pretty rare. It can only be observed if running
with a high number of concurrent connections in parallel, so that the
random generator will provide duplicate values. Patch is still labelled
as MEDIUM as this modifies code paths used frequently.

To fix this, _quic_cid_insert() unsafe function is completely removed.
Instead, quic_cid_insert() can be used, which reports an error code if a
collision happens. CID are then stored in the quic_conn tree only after
global tree insert success. Here is the solution for each steps if a
collision occurs :
* on init as client: the connection is completely released
* post-handshake: the CID is immediately released. The connection is
  kept, but it will miss an extra CID.
* on RETIRE_CONNECTION_ID parsing: a loop is implemented to retry random
  generation. It it fails several times, the connection is closed in
  error.

A small convenience change is made to quic_cid_insert(). Output
parameter <new_tid> can now be NULL, which is useful as most of the
times caller do not care about it.

This must be backported up to 2.6.
2025-11-10 12:10:14 +01:00
Amaury Denoyelle
419e5509d8 MINOR: quic: split CID alloc/generation function
Split new_quic_cid() function into multiple ones. This patch should not
introduce any visible change. The objective is to render CID allocation
and generation more modular.

The first advantage of this patch is to bring code simplication. In
particular, conn CID sequence number increment and insertion into
connection tree is simpler than before. Another improvment is also that
errors could now be handled easier at each different steps of the CID
init.

This patch is a prerequisite for the fix on CID collision, thus it must
be backported prior to it to every affected version.
2025-11-10 12:10:14 +01:00
Amaury Denoyelle
0ef473ba6b MINOR: quic: adjust CID conn tree alloc in qc_new_conn()
Change qc_new_conn() so that the connection CID tree is allocated
earlier in the function. This patch does not introduce a behavior
change. Its objective is to facilitate future evolutions on CIDs
handling.

This patch is a prerequisite for the fix on CID collision, thus it must
be backported prior to it to every affected version.
2025-11-10 12:10:14 +01:00
Amaury Denoyelle
73621adb23 BUG/MINOR: quic: close connection on CID alloc failure
During RETIRE_CONNECTION_ID frame parsing, a new connection ID is
immediately reallocated after the release of the previous one. This is
done to ensure that the peer will never run out of DCID.

Prior to this patch, a CID allocation failure was be silently ignored.
This prevent the emission of a new CID, which could prevent the peer to
emit packets if it had no other CIDs available for use. Now, such error
is considered fatal to the connection. This is the safest solution as
it's better to close connections when memory is running low.

It must be backported up to 2.8.
2025-11-10 12:10:14 +01:00
Willy Tarreau
137d5ba93f BUG/MEDIUM: config: for word expansion, empty or non-existing are the same
Amaury reported a case where "${FOO[*]}" still produces an empty field.
It happens if the variable is defined but does not contain any non-space
characters. The reason is that we special-case word expansion only on
non-existing vars. Let's change the ordering of operations so that word-
expanded vars always pretend the current arg is not an empty quote, so
that we don't make any difference between a non-existing var and an
empty one.

No backport is needed unless commit 1968731765 ("BUG/MEDIUM: config:
solve the empty argument problem again") is.
2025-11-10 11:59:35 +01:00
374 changed files with 12836 additions and 5564 deletions

View File

@ -19,7 +19,7 @@ defaults
frontend h2
mode http
bind 127.0.0.1:8443 ssl crt reg-tests/ssl/common.pem alpn h2,http/1.1
bind 127.0.0.1:8443 ssl crt reg-tests/ssl/certs/common.pem alpn h2,http/1.1
default_backend h2b
backend h2b

View File

@ -28,7 +28,7 @@ jobs:
run: env SSL_LIB=${HOME}/opt/ scripts/build-curl.sh
- name: Compile HAProxy
run: |
make -j$(nproc) ERR=1 CC=gcc TARGET=linux-glibc \
make -j$(nproc) CC=gcc TARGET=linux-glibc \
USE_QUIC=1 USE_OPENSSL=1 USE_ECH=1 \
SSL_LIB=${HOME}/opt/lib SSL_INC=${HOME}/opt/include \
DEBUG="-DDEBUG_POOL_INTEGRITY -DDEBUG_UNIT" \

77
.github/workflows/openssl-master.yml vendored Normal file
View File

@ -0,0 +1,77 @@
name: openssl master
on:
schedule:
- cron: "0 3 * * *"
workflow_dispatch:
permissions:
contents: read
jobs:
test:
runs-on: ubuntu-latest
if: ${{ github.repository_owner == 'haproxy' || github.event_name == 'workflow_dispatch' }}
steps:
- uses: actions/checkout@v5
- name: Install apt dependencies
run: |
sudo apt-get update -o Acquire::Languages=none -o Acquire::Translation=none
sudo apt-get --no-install-recommends -y install socat gdb
sudo apt-get --no-install-recommends -y install libpsl-dev
- uses: ./.github/actions/setup-vtest
- name: Install OpenSSL master
run: env OPENSSL_VERSION="git-master" GIT_TYPE="branch" scripts/build-ssl.sh
- name: Compile HAProxy
run: |
make -j$(nproc) ERR=1 CC=gcc TARGET=linux-glibc \
USE_QUIC=1 USE_OPENSSL=1 \
SSL_LIB=${HOME}/opt/lib SSL_INC=${HOME}/opt/include \
DEBUG="-DDEBUG_POOL_INTEGRITY -DDEBUG_UNIT" \
ADDLIB="-Wl,-rpath,/usr/local/lib/ -Wl,-rpath,$HOME/opt/lib/"
sudo make install
- name: Show HAProxy version
id: show-version
run: |
ldd $(which haproxy)
haproxy -vv
echo "version=$(haproxy -v |awk 'NR==1{print $3}')" >> $GITHUB_OUTPUT
- name: Install problem matcher for VTest
run: echo "::add-matcher::.github/vtest.json"
- name: Run VTest for HAProxy
id: vtest
run: |
# This is required for macOS which does not actually allow to increase
# the '-n' soft limit to the hard limit, thus failing to run.
ulimit -n 65536
# allow to catch coredumps
ulimit -c unlimited
make reg-tests VTEST_PROGRAM=../vtest/vtest REGTESTS_TYPES=default,bug,devel
- name: Show VTest results
if: ${{ failure() && steps.vtest.outcome == 'failure' }}
run: |
for folder in ${TMPDIR:-/tmp}/haregtests-*/vtc.*; do
printf "::group::"
cat $folder/INFO
cat $folder/LOG
echo "::endgroup::"
done
exit 1
- name: Run Unit tests
id: unittests
run: |
make unit-tests
- name: Show coredumps
if: ${{ failure() && steps.vtest.outcome == 'failure' }}
run: |
failed=false
shopt -s nullglob
for file in /tmp/core.*; do
failed=true
printf "::group::"
gdb -ex 'thread apply all bt full' ./haproxy $file
echo "::endgroup::"
done
if [ "$failed" = true ]; then
exit 1;
fi

View File

@ -1,32 +0,0 @@
#
# special purpose CI: test against OpenSSL built in "no-deprecated" mode
# let us run those builds weekly
#
# for example, OpenWRT uses such OpenSSL builds (those builds are smaller)
#
#
# some details might be found at NL: https://www.mail-archive.com/haproxy@formilux.org/msg35759.html
# GH: https://github.com/haproxy/haproxy/issues/367
name: openssl no-deprecated
on:
schedule:
- cron: "0 0 * * 4"
workflow_dispatch:
permissions:
contents: read
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: ./.github/actions/setup-vtest
- name: Compile HAProxy
run: |
make DEFINE="-DOPENSSL_API_COMPAT=0x10100000L -DOPENSSL_NO_DEPRECATED" -j3 CC=gcc ERR=1 TARGET=linux-glibc USE_OPENSSL=1
- name: Run VTest
run: |
make reg-tests VTEST_PROGRAM=../vtest/vtest REGTESTS_TYPES=default,bug,devel

View File

@ -113,7 +113,7 @@ jobs:
DEBUG="-DDEBUG_POOL_INTEGRITY -DDEBUG_UNIT" \
${{ join(matrix.FLAGS, ' ') }} \
ADDLIB="-Wl,-rpath,/usr/local/lib/ -Wl,-rpath,$HOME/opt/lib/"
sudo make install
sudo make install-bin
- name: Compile admin/halog/halog
run: |
make -j$(nproc) admin/halog/halog \

290
CHANGELOG
View File

@ -1,6 +1,296 @@
ChangeLog :
===========
2026/01/07 : 3.4-dev2
- BUG/MEDIUM: mworker/listener: ambiguous use of RX_F_INHERITED with shards
- BUG/MEDIUM: http-ana: Properly detect client abort when forwarding response (v2)
- BUG/MEDIUM: stconn: Don't report abort from SC if read0 was already received
- BUG/MEDIUM: quic: Don't try to use hystart if not implemented
- CLEANUP: backend: Remove useless test on server's xprt
- CLEANUP: tcpcheck: Remove useless test on the xprt used for healthchecks
- CLEANUP: ssl-sock: Remove useless tests on connection when resuming TLS session
- REGTESTS: quic: fix a TLS stack usage
- REGTESTS: list all skipped tests including 'feature cmd' ones
- CI: github: remove openssl no-deprecated job
- CI: github: add a job to test the master branch of OpenSSL
- CI: github: openssl-master.yml misses actions/checkout
- BUG/MEDIUM: backend: Do not remove CO_FL_SESS_IDLE in assign_server()
- CI: github: use git prefix for openssl-master.yml
- BUG/MEDIUM: mux-h2: synchronize all conditions to create a new backend stream
- REGTESTS: fix error when no test are skipped
- MINOR: cpu-topo: Turn the cpu policy configuration into a struct
- MEDIUM: cpu-topo: Add a "threads-per-core" keyword to cpu-policy
- MEDIUM: cpu-topo: Add a "cpu-affinity" option
- MEDIUM: cpu-topo: Add a new "max-threads-per-group" global keyword
- MEDIUM: cpu-topo: Add the "per-thread" cpu_affinity
- MEDIUM: cpu-topo: Add the "per-ccx" cpu_affinity
- BUG/MINOR: cpu-topo: fix -Wlogical-not-parentheses build with clang
- DOC: config: fix number of values for "cpu-affinity"
- MINOR: tools: add a secure implementation of memset
- MINOR: mux-h2: add missing glitch count for non-decodable H2 headers
- MINOR: mux-h2: perform a graceful close at 75% glitches threshold
- MEDIUM: mux-h1: implement basic glitches support
- MINOR: mux-h1: perform a graceful close at 75% glitches threshold
- MEDIUM: cfgparse: acknowledge that proxy ID auto numbering starts at 2
- MINOR: cfgparse: remove useless checks on no server in backend
- OPTIM/MINOR: proxy: do not init proxy management task if unused
- MINOR: patterns: preliminary changes for reorganization
- MEDIUM: patterns: reorganize pattern reference elements
- CLEANUP: patterns: remove dead code
- OPTIM: patterns: cache the current generation
- MINOR: tcp: add new bind option "tcp-ss" to instruct the kernel to save the SYN
- MINOR: protocol: support a generic way to call getsockopt() on a connection
- MINOR: tcp: implement the get_opt() function
- MINOR: tcp_sample: implement the fc_saved_syn sample fetch function
- CLEANUP: assorted typo fixes in the code, commits and doc
- BUG/MEDIUM: cpu-topo: Don't forget to reset visited_ccx.
- BUG/MAJOR: set the correct generation ID in pat_ref_append().
- BUG/MINOR: backend: fix the conn_retries check for TFO
- BUG/MINOR: backend: inspect request not response buffer to check for TFO
- MINOR: net_helper: add sample converters to decode ethernet frames
- MINOR: net_helper: add sample converters to decode IP packet headers
- MINOR: net_helper: add sample converters to decode TCP headers
- MINOR: net_helper: add ip.fp() to build a simplified fingerprint of a SYN
- MINOR: net_helper: prepare the ip.fp() converter to support more options
- MINOR: net_helper: add an option to ip.fp() to append the TTL to the fingerprint
- MINOR: net_helper: add an option to ip.fp() to append the source address
- DOC: config: fix the length attribute name for stick tables of type binary / string
- MINOR: mworker/cli: only keep positive PIDs in proc_list
- CLEANUP: mworker: remove duplicate list.h include
- BUG/MINOR: mworker/cli: fix show proc pagination using reload counter
- MINOR: mworker/cli: extract worker "show proc" row printer
- MINOR: cpu-topo: Factorize code
- MINOR: cpu-topo: Rename variables to better fit their usage
- BUG/MEDIUM: peers: Properly handle shutdown when trying to get a line
- BUG/MEDIUM: mux-h1: Take care to update <kop> value during zero-copy forwarding
- MINOR: threads: Avoid using a thread group mask when stopping.
- MINOR: hlua: Add support for lua 5.5
- MEDIUM: cpu-topo: Add an optional directive for per-group affinity
- BUG/MEDIUM: mworker: can't use signals after a failed reload
- BUG/MEDIUM: stconn: Move data from <kip> to <kop> during zero-copy forwarding
- DOC: config: fix a few typos and refine cpu-affinity
- MINOR: receiver: Remove tgroup_mask from struct shard_info
- BUG/MINOR: quic: fix deprecated warning for window size keyword
2025/12/10 : 3.4-dev1
- BUG/MINOR: jwt: Missing "case" in switch statement
- DOC: configuration: ECH support details
- Revert "MINOR: quic: use dynamic cc_algo on bind_conf"
- MINOR: quic: define quic_cc_algo as const
- MINOR: quic: extract cc-algo parsing in a dedicated function
- MINOR: quic: implement cc-algo server keyword
- BUG/MINOR: quic-be: Missing keywords array NULL termination
- REGTESTS: ssl enable tls12_reuse.vtc for AWS-LC
- REGTESTS: ssl: split tls*_reuse in stateless and stateful resume tests
- BUG/MEDIUM: connection: fix "bc_settings_streams_limit" typo
- BUG/MEDIUM: config: ignore empty args in skipped blocks
- DOC: config: mention clearer that the cache's total-max-size is mandatory
- DOC: config: reorder the cache section's keywords
- BUG/MINOR: quic/ssl: crash in ClientHello callback ssl traces
- BUG/MINOR: quic-be: handshake errors without connection stream closure
- MINOR: quic: Add useful debugging traces in qc_idle_timer_do_rearm()
- REGTESTS: ssl: Move all the SSL certificates, keys, crt-lists inside "certs" directory
- REGTESTS: quic/ssl: ssl/del_ssl_crt-list.vtc supported by QUIC
- REGTESTS: quic: dynamic_server_ssl.vtc supported by QUIC
- REGTESTS: quic: issuers_chain_path.vtc supported by QUIC
- REGTESTS: quic: new_del_ssl_cafile.vtc supported by QUIC
- REGTESTS: quic: ocsp_auto_update.vtc supported by QUIC
- REGTESTS: quic: set_ssl_bug_2265.vtc supported by QUIC
- MINOR: quic: avoid code duplication in TLS alert callback
- BUG/MINOR: quic-be: missing connection stream closure upon TLS alert to send
- REGTESTS: quic: set_ssl_cafile.vtc supported by QUIC
- REGTESTS: quic: set_ssl_cert_noext.vtc supported by QUIC
- REGTESTS: quic: set_ssl_cert.vtc supported by QUIC
- REGTESTS: quic: set_ssl_crlfile.vtc supported by QUIC
- REGTESTS: quic: set_ssl_server_cert.vtc supported by QUIC
- REGTESTS: quic: show_ssl_ocspresponse.vtc supported by QUIC
- REGTESTS: quic: ssl_client_auth.vtc supported by QUIC
- REGTESTS: quic: ssl_client_samples.vtc supported by QUIC
- REGTESTS: quic: ssl_default_server.vtc supported by QUIC
- REGTESTS: quic: new_del_ssl_crlfile.vtc supported by QUIC
- REGTESTS: quic: ssl_frontend_samples.vtc supported by QUIC
- REGTESTS: quic: ssl_server_samples.vtc supported by QUIC
- REGTESTS: quic: ssl_simple_crt-list.vtc supported by QUIC
- REGTESTS: quic: ssl_sni_auto.vtc code provision for QUIC
- REGTESTS: quic: ssl_curve_name.vtc supported by QUIC
- REGTESTS: quic: add_ssl_crt-list.vtc supported by QUIC
- REGTESTS: add ssl_ciphersuites.vtc (TCP & QUIC)
- BUG/MINOR: quic: do not set first the default QUIC curves
- REGTESTS: quic/ssl: Add ssl_curves_selection.vtc
- BUG/MINOR: ssl: Don't allow to set NULL sni
- MEDIUM: quic: Add connection as argument when qc_new_conn() is called
- MINOR: ssl: Add a function to hash SNIs
- MINOR: ssl: Store hash of the SNI for cached TLS sessions
- MINOR: ssl: Compare hashes instead of SNIs when a session is cached
- MINOR: connection/ssl: Store the SNI hash value in the connection itself
- MEDIUM: tcpcheck/backend: Get the connection SNI before initializing SSL ctx
- BUG/MEDIUM: ssl: Don't reuse TLS session if the connection's SNI differs
- MEDIUM: ssl/server: No longer store the SNI of cached TLS sessions
- BUG/MINOR: log: Dump good %B and %U values in logs
- BUG/MEDIUM: http-ana: Don't close server connection on read0 in TUNNEL mode
- DOC: config: Fix description of the spop mode
- DOC: config: Improve spop mode documentation
- MINOR: ssl: Split ssl_crt-list_filters.vtc in two files by TLS version
- REGTESTS: quic: tls13_ssl_crt-list_filters.vtc supported by QUIC
- BUG/MEDIUM: h3: do not access QCS <sd> if not allocated
- CLEANUP: mworker/cli: remove useless variable
- BUG/MINOR: mworker/cli: 'show proc' is limited by buffer size
- BUG/MEDIUM: ssl: Always check the ALPN after handshake
- MINOR: connections: Add a new CO_FL_SSL_NO_CACHED_INFO flag
- BUG/MEDIUM: ssl: Don't store the ALPN for check connections
- BUG/MEDIUM: ssl: Don't resume session for check connections
- CLEANUP: improvements to the alignment macros
- CLEANUP: use the automatic alignment feature
- CLEANUP: more conversions and cleanups for alignment
- BUG/MEDIUM: h3: fix access to QCS <sd> definitely
- MINOR: h2/trace: emit a trace of the received RST_STREAM type
2025/11/26 : 3.4-dev0
- MINOR: version: mention that it's development again
2025/11/26 : 3.3.0
- BUG/MINOR: acme: better challenge_ready processing
- BUG/MINOR: acme: warning ctx may be used uninitialized
- MINOR: httpclient: complete the https log
- BUG/MEDIUM: server: do not use default SNI if manually set
- BUG/MINOR: freq_ctr: Prevent possible signed overflow in freq_ctr_overshoot_period
- DOC: ssl: Document the restrictions on 0RTT.
- DOC: ssl: Note that 0rtt works fork QUIC with QuicTLS too.
- BUG/MEDIUM: quic: do not prevent sending if no BE token
- BUG/MINOR: quic/server: free quic_retry_token on srv drop
- MINOR: quic: split global CID tree between FE and BE sides
- MINOR: quic: use separate global quic_conns FE/BE lists
- MINOR: quic: add "clo" filter on show quic
- MINOR: quic: dump backend connections on show quic
- MINOR: quic: mark backend conns on show quic
- BUG/MINOR: quic: fix uninit list on show quic handler
- BUG/MINOR: quic: release BE quic_conn on connect failure
- BUG/MINOR: server: fix srv_drop() crash on partially init srv
- BUG/MINOR: h3: do no crash on forwarding multiple chained response
- BUG/MINOR: h3: handle properly buf alloc failure on response forwarding
- BUG/MEDIUM: server/ssl: Unset the SNI for new server connections if none is set
- BUG/MINOR: acme: fix ha_alert() call
- Revert "BUG/MEDIUM: server/ssl: Unset the SNI for new server connections if none is set"
- BUG/MINOR: sock-inet: ignore conntrack for transparent sockets on Linux
- DEV: patchbot: prepare for new version 3.4-dev
- DOC: update INSTALL with the range of gcc compilers and openssl versions
- MINOR: version: mention that 3.3 is stable now
2025/11/21 : 3.3-dev14
- MINOR: stick-tables: Rename stksess shards to use buckets
- MINOR: quic: do not use quic_newcid_from_hash64 on BE side
- MINOR: quic: support multiple random CID generation for BE side
- MINOR: quic: try to clarify quic_conn CIDs fields direction
- MINOR: quic: refactor qc_new_conn() prototype
- MINOR: quic: remove <ipv4> arg from qc_new_conn()
- MEDIUM: mworker: set the mworker-max-reloads to 50
- BUG/MEDIUM: quic-be: prevent use of MUX for 0-RTT sessions without secrets
- CLEANUP: startup: move confusing msg variable
- BUG/MEDIUM: mworker: signals inconsistencies during startup and reload
- BUG/MINOR: mworker: wrong signals during startup
- BUG/MINOR: acme: P-256 doesn't work with openssl >= 3.0
- REGTESTS: ssl: split the SSL reuse test into TLS 1.2/1.3
- BUILD: Makefile: make install with admin tools
- CI: github: make install-bin instead of make install
- BUG/MINOR: ssl: remove dead code in ssl_sock_from_buf()
- BUG/MINOR: mux-quic: implement max-reuse server parameter
- MINOR: quic: fix trace on quic_conn_closed release
- BUG/MINOR: quic: do not decrement jobs for backend conns
- BUG/MINOR: quic: fix FD usage for quic_conn_closed on backend side
- BUILD: Makefile: remove halog from install-admin
- REGTESTS: ssl: add basic 0rtt tests for TLSv1.2, TLSv1.3 and QUIC
- REGTESTS: ssl: also verify that 0-rtt properly advertises early-data:1
- MINOR: quic/flags: add missing QUIC flags for flags dev tool.
- MINOR: quic: uneeded xprt context variable passed as parameter
- MINOR: limits: keep a copy of the rough estimate of needed FDs in global struct
- MINOR: limits: explain a bit better what to do when fd limits are exceeded
- BUG/MEDIUM: quic-be/ssl_sock: TLS callback called without connection
- BUG/MINOR: acme: alert when the map doesn't exist at startup
- DOC: acme: add details about the DNS-01 support
- DOC: acme: explain how to dump the certificates
- DOC: acme: configuring acme needs a crt file
- DOC: acme: add details about key pair generation in ACME section
- BUG/MEDIUM: queues: Don't forget to unlock the queue before exiting
- MINOR: muxes: Support an optional ALPN string when defining mux protocols
- MINOR: config: Do proto detection for listeners before checks about ALPN
- BUG/MEDIUM: config: Use the mux protocol ALPN by default for listeners if forced
- DOC: config: Add a note about conflict with ALPN/NPN settings and proto keyword
- MINOR: quic: store source address for backend conns
- BUG/MINOR: quic: flag conn with CO_FL_FDLESS on backend side
- ADMIN: dump-certs: let dry-run compare certificates
- BUG/MEDIUM: connection/ssl: also fix the ssl_sock_io_cb() regarding idle list
- DOC: http: document 413 response code
- MINOR: limits: display the computed maxconn using ha_notice()
- BUG/MEDIUM: applet: Fix conditions to detect spinning loop with the new API
- BUG/MEDIUM: cli: State the cli have no more data to deliver if it yields
- MINOR: h3: adjust sedesc update for known input payload len
- BUG/MINOR: mux-quic: fix sedesc leak on BE side
- OPTIM: mux-quic: delay FE sedesc alloc to stream creation
- BUG/MEDIUM: quic-be: quic_conn_closed buffer overflow
- BUG/MINOR: mux-quic: check access on qcs stream-endpoint
- BUG/MINOR: acme: handle multiple auth with the same name
- BUG/MINOR: acme: prevent creating map entries with dns-01
2025/11/14 : 3.3-dev13
- BUG/MEDIUM: config: for word expansion, empty or non-existing are the same
- BUG/MINOR: quic: close connection on CID alloc failure
- MINOR: quic: adjust CID conn tree alloc in qc_new_conn()
- MINOR: quic: split CID alloc/generation function
- BUG/MEDIUM: quic: handle collision on CID generation
- MINOR: quic: extend traces on CID allocation
- MEDIUM/OPTIM: quic: alloc quic_conn after CID collision check
- MINOR: stats-proxy: ensure future-proof FN_AGE manipulation in me_generate_field()
- BUG/MEDIUM: stats-file: fix shm-stats-file preload not working anymore
- BUG/MINOR: do not account backend connections into maxconn
- BUG/MEDIUM: init: 'devnullfd' not properly closed for master
- BUG/MINOR: acme: more explicit error when BIO_new_file()
- BUG/MEDIUM: quic-be: do not launch the connection migration process
- MINOR: quic-be: Parse the NEW_TOKEN frame
- MEDIUM: quic-be: Parse, store and reuse tokens provided by NEW_TOKEN
- MINOR: quic-be: helper functions to save/restore transport params (0-RTT)
- MINOR: quic-be: helper quic_reuse_srv_params() function to reuse server params (0-RTT)
- MINOR: quic-be: Save the backend 0-RTT parameters
- MEDIUM: quic-be: modify ssl_sock_srv_try_reuse_sess() to reuse backend sessions (0-RTT)
- MINOR: quic-be: allow the preparation of 0-RTT packets
- MINOR: quic-be: Send post handshake frames from list of frames (0-RTT)
- MEDIUM: quic-be: qc_send_mux() adaptation for 0-RTT
- MINOR: quic-be: discard the 0-RTT keys
- MEDIUM: quic-be: enable the use of 0-RTT
- MINOR: quic-be: validate the 0-RTT transport parameters
- MINOR: quic-be: do not create the mux after handshake completion (for 0-RTT)
- MINOR: quic-be: avoid a useless I/O callback wakeup for 0-RTT sessions
- BUG/MEDIUM: acme: move from mt_list to a rwlock + ebmbtree
- BUG/MINOR: acme: can't override the default resolver
- MINOR: ssl/sample: expose ssl_*c_curve for AWS-LC
- MINOR: check: delay MUX init when SSL ALPN is used
- MINOR: cfgdiag: adjust diag on servers
- BUG/MINOR: check: only try connection reuse for http-check rulesets
- BUG/MINOR: check: fix reuse-pool if MUX inherited from server
- MINOR: check: clarify check-reuse-pool interaction with reuse policy
- DOC: configuration: add missing ssllib_name_startswith()
- DOC: configuration: add missing openssl_version predicates
- MINOR: cfgcond: add "awslc_api_atleast" and "awslc_api_before"
- REGTESTS: ssl: activate ssl_curve_name.vtc for AWS-LC
- BUILD: ech: fix clang warnings
- BUG/MEDIUM: stick-tables: Always return the good stksess from stktable_set_entry
- BUG/MINOR: stick-tables: Fix return value for __stksess_kill()
- CLEANUP: stick-tables: Don't needlessly compute shard number in stksess_free()
- MINOR: h1: h1_release() should return if it destroyed the connection
- BUG/MEDIUM: h1: prevent a crash on HTTP/2 upgrade
- MINOR: check: use auto SNI for QUIC checks
- MINOR: check: ensure QUIC checks configuration coherency
- CLEANUP: peers: remove an unneeded null check
- Revert "BUG/MEDIUM: connections: permit to permanently remove an idle conn"
- BUG/MEDIUM: connection: do not reinsert a purgeable conn in idle list
- DEBUG: extend DEBUG_STRESS to ease testing and turn on extra checks
- DEBUG: add BUG_ON_STRESS(): a BUG_ON() implemented only when DEBUG_STRESS > 0
- DEBUG: servers: add a few checks for stress-testing idle conns
- BUG/MINOR: check: fix QUIC check test when QUIC disabled
- BUG/MINOR: quic-be: missing version negotiation
- CLEANUP: quic: Missing succesful SSL handshake backend trace (OpenSSL 3.5)
- BUG/MINOR: quic-be: backend SSL session reuse fix (OpenSSL 3.5)
- REGTEST: quic: quic/ssl_reuse.vtc supports OpenSSL 3.5 QUIC API
2025/11/08 : 3.3-dev12
- MINOR: quic: enable SSL on QUIC servers automatically
- MINOR: quic: reject conf with QUIC servers if not compiled

18
INSTALL
View File

@ -111,7 +111,7 @@ HAProxy requires a working GCC or Clang toolchain and GNU make :
may want to retry with "gmake" which is the name commonly used for GNU make
on BSD systems.
- GCC >= 4.7 (up to 14 tested). Older versions are no longer supported due to
- GCC >= 4.7 (up to 15 tested). Older versions are no longer supported due to
the latest mt_list update which only uses c11-like atomics. Newer versions
may sometimes break due to compiler regressions or behaviour changes. The
version shipped with your operating system is very likely to work with no
@ -237,7 +237,7 @@ to forcefully enable it using "USE_LIBCRYPT=1".
-----------------
For SSL/TLS, it is necessary to use a cryptography library. HAProxy currently
supports the OpenSSL library, and is known to build and work with branches
1.0.0, 1.0.1, 1.0.2, 1.1.0, 1.1.1, and 3.0 to 3.5. It is recommended to use
1.0.0, 1.0.1, 1.0.2, 1.1.0, 1.1.1, and 3.0 to 3.6. It is recommended to use
at least OpenSSL 1.1.1 to have support for all SSL keywords and configuration
in HAProxy. OpenSSL follows a long-term support cycle similar to HAProxy's,
and each of the branches above receives its own fixes, without forcing you to
@ -259,11 +259,15 @@ reported to work as well. While there are some efforts from the community to
ensure they work well, OpenSSL remains the primary target and this means that
in case of conflicting choices, OpenSSL support will be favored over other
options. Note that QUIC is not fully supported when haproxy is built with
OpenSSL < 3.5 version. In this case, QUICTLS is the preferred alternative.
As of writing this, the QuicTLS project follows OpenSSL very closely and provides
update simultaneously, but being a volunteer-driven project, its long-term future
does not look certain enough to convince operating systems to package it, so it
needs to be build locally. See the section about QUIC in this document.
OpenSSL < 3.5.2 version. In this case, QUICTLS or AWS-LC are the preferred
alternatives. As of writing this, the QuicTLS project follows OpenSSL very
closely and provides update simultaneously, but being a volunteer-driven
project, its long-term future does not look certain enough to convince
operating systems to package it, so it needs to be build locally. Recent
versions of AWS-LC (>= 1.22 and the FIPS branches) are pretty complete and
generally more performant than other OpenSSL derivatives, but may behave
slightly differently, particularly when dealing with outdated setups. See
the section about QUIC in this document.
A fifth option is wolfSSL (https://github.com/wolfSSL/wolfssl). It is the only
supported alternative stack not based on OpenSSL, yet which implements almost

View File

@ -643,7 +643,7 @@ ifneq ($(USE_OPENSSL:0=),)
OPTIONS_OBJS += src/ssl_sock.o src/ssl_ckch.o src/ssl_ocsp.o src/ssl_crtlist.o \
src/ssl_sample.o src/cfgparse-ssl.o src/ssl_gencert.o \
src/ssl_utils.o src/jwt.o src/ssl_clienthello.o src/jws.o src/acme.o \
src/ssl_trace.o
src/ssl_trace.o src/jwe.o
endif
ifneq ($(USE_ENGINE:0=),)
@ -992,7 +992,7 @@ OBJS += src/mux_h2.o src/mux_h1.o src/mux_fcgi.o src/log.o \
src/cfgcond.o src/proto_udp.o src/lb_fwlc.o src/ebmbtree.o \
src/proto_uxdg.o src/cfgdiag.o src/sock_unix.o src/sha1.o \
src/lb_fas.o src/clock.o src/sock_inet.o src/ev_select.o \
src/lb_map.o src/shctx.o src/hpack-dec.o \
src/lb_map.o src/shctx.o src/hpack-dec.o src/net_helper.o \
src/arg.o src/signal.o src/fix.o src/dynbuf.o src/guid.o \
src/cfgparse-tcp.o src/lb_ss.o src/chunk.o src/counters.o \
src/cfgparse-unix.o src/regex.o src/fcgi.o src/uri_auth.o \
@ -1123,6 +1123,11 @@ install-doc:
$(INSTALL) -m 644 doc/$$x.txt "$(DESTDIR)$(DOCDIR)" ; \
done
install-admin:
$(Q)$(INSTALL) -d "$(DESTDIR)$(SBINDIR)"
$(Q)$(INSTALL) admin/cli/haproxy-dump-certs "$(DESTDIR)$(SBINDIR)"
$(Q)$(INSTALL) admin/cli/haproxy-reload "$(DESTDIR)$(SBINDIR)"
install-bin:
$(Q)for i in haproxy $(EXTRA); do \
if ! [ -e "$$i" ]; then \
@ -1133,7 +1138,7 @@ install-bin:
$(Q)$(INSTALL) -d "$(DESTDIR)$(SBINDIR)"
$(Q)$(INSTALL) haproxy $(EXTRA) "$(DESTDIR)$(SBINDIR)"
install: install-bin install-man install-doc
install: install-bin install-admin install-man install-doc
uninstall:
$(Q)rm -f "$(DESTDIR)$(MANDIR)"/man1/haproxy.1

View File

@ -1,2 +1,2 @@
$Format:%ci$
2025/11/08
2026/01/07

View File

@ -1 +1 @@
3.3-dev12
3.4-dev2

View File

@ -103,6 +103,11 @@ dump_certificate() {
return 0
fi
# dry run will just return before trying to move the files
if [ "${DRY_RUN}" != "0" ]; then
return 0
fi
# move the current certificates to ".old.timestamp"
if [ -f "${prev_crt}" ] && [ -f "${prev_key}" ]; then
mv "${prev_crt}" "${prev_crt}.${d}"
@ -123,7 +128,7 @@ dump_all_certificates() {
export KEY_FILENAME
if read_certificate "$line"; then
[ "${DRY_RUN}" = "0" ] && dump_certificate "$NAME" "$CRT_FILENAME" "$KEY_FILENAME"
dump_certificate "$NAME" "$CRT_FILENAME" "$KEY_FILENAME"
else
echo "[WARNING] ($$) : can't dump \"$name\", crt/key filename details not found in \"show ssl cert\"" >&2
fi

View File

@ -55,7 +55,7 @@ usage() {
echo " -S, --master-socket <path> Use the master socket at <path> (default: ${MASTER_SOCKET})"
echo " -d, --debug Debug mode, set -x"
echo " -t, --timeout Timeout (socat -t) (default: ${TIMEOUT})"
echo " -s, --silent Slient mode (no output)"
echo " -s, --silent Silent mode (no output)"
echo " -v, --verbose Verbose output (output from haproxy on failure)"
echo " -vv Even more verbose output (output from haproxy on success and failure)"
echo " -h, --help This help"

View File

@ -59,9 +59,9 @@ struct ring_v2 {
struct ring_v2a {
size_t size; // storage size
size_t rsvd; // header length (used for file-backed maps)
size_t tail __attribute__((aligned(64))); // storage tail
size_t head __attribute__((aligned(64))); // storage head
char area[0] __attribute__((aligned(64))); // storage area begins immediately here
size_t tail ALIGNED(64); // storage tail
size_t head ALIGNED(64); // storage head
char area[0] ALIGNED(64); // storage area begins immediately here
};
/* display the message and exit with the code */

View File

@ -0,0 +1,70 @@
BEGININPUT
BEGINCONTEXT
HAProxy's development cycle consists in one development branch, and multiple
maintenance branches.
All the development is made into the development branch exclusively. This
includes mostly new features, doc updates, cleanups and or course, fixes.
The maintenance branches, also called stable branches, never see any
development, and only receive ultra-safe fixes for bugs that affect them,
that are picked from the development branch.
Branches are numbered in 0.1 increments. Every 6 months, upon a new major
release, the development branch enters maintenance and a new development branch
is created with a new, higher version. The current development branch is
3.4-dev, and maintenance branches are 3.3 and below.
Fixes created in the development branch for issues that were introduced in an
earlier branch are applied in descending order to each and every version till
that branch that introduced the issue: 3.3 first, then 3.2, then 3.1, then 3.0
and so on. This operation is called "backporting". A fix for an issue is never
backported beyond the branch that introduced the issue. An important point is
that the project maintainers really aim at zero regression in maintenance
branches, so they're never willing to take any risk backporting patches that
are not deemed strictly necessary.
Fixes consist of patches managed using the Git version control tool and are
identified by a Git commit ID and a commit message. For this reason we
indistinctly talk about backporting fixes, commits, or patches; all mean the
same thing. When mentioning commit IDs, developers always use a short form
made of the first 8 characters only, and expect the AI assistant to do the
same.
It seldom happens that some fixes depend on changes that were brought by other
patches that were not in some branches and that will need to be backported as
well for the fix to work. In this case, such information is explicitly provided
in the commit message by the patch's author in natural language.
Developers are serious and always indicate if a patch needs to be backported.
Sometimes they omit the exact target branch, or they will say that the patch is
"needed" in some older branch, but it means the same. If a commit message
doesn't mention any backport instructions, it means that the commit does not
have to be backported. And patches that are not strictly bug fixes nor doc
improvements are normally not backported. For example, fixes for design
limitations, architectural improvements and performance optimizations are
considered too risky for a backport. Finally, all bug fixes are tagged as
"BUG" at the beginning of their subject line. Patches that are not tagged as
such are not bugs, and must never be backported unless their commit message
explicitly requests so.
ENDCONTEXT
A developer is reviewing the development branch, trying to spot which commits
need to be backported to maintenance branches. This person is already expert
on HAProxy and everything related to Git, patch management, and the risks
associated with backports, so he doesn't want to be told how to proceed nor to
review the contents of the patch.
The goal for this developer is to get some help from the AI assistant to save
some precious time on this tedious review work. In order to do a better job, he
needs an accurate summary of the information and instructions found in each
commit message. Specifically he needs to figure if the patch fixes a problem
affecting an older branch or not, if it needs to be backported, if so to which
branches, and if other patches need to be backported along with it.
The indented text block below after an "id" line and starting with a Subject line
is a commit message from the HAProxy development branch that describes a patch
applied to that branch, starting with its subject line, please read it carefully.

View File

@ -0,0 +1,29 @@
ENDINPUT
BEGININSTRUCTION
You are an AI assistant that follows instruction extremely well. Help as much
as you can, responding to a single question using a single response.
The developer wants to know if he needs to backport the patch above to fix
maintenance branches, for which branches, and what possible dependencies might
be mentioned in the commit message. Carefully study the commit message and its
backporting instructions if any (otherwise it should probably not be backported),
then provide a very concise and short summary that will help the developer decide
to backport it, or simply to skip it.
Start by explaining in one or two sentences what you recommend for this one and why.
Finally, based on your analysis, give your general conclusion as "Conclusion: X"
where X is a single word among:
- "yes", if you recommend to backport the patch right now either because
it explicitly states this or because it's a fix for a bug that affects
a maintenance branch (3.3 or lower);
- "wait", if this patch explicitly mentions that it must be backported, but
only after waiting some time.
- "no", if nothing clearly indicates a necessity to backport this patch (e.g.
lack of explicit backport instructions, or it's just an improvement);
- "uncertain" otherwise for cases not covered above
ENDINSTRUCTION
Explanation:

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
-----------------------
HAProxy Starter Guide
-----------------------
version 3.3
version 3.4
This document is an introduction to HAProxy for all those who don't know it, as

View File

@ -1,7 +1,7 @@
------------------------
HAProxy Management Guide
------------------------
version 3.3
version 3.4
This document describes how to start, stop, manage, and troubleshoot HAProxy,
@ -2474,6 +2474,11 @@ prompt [help | n | i | p | timed]*
advanced scripts, and the non-interactive mode (default) to basic scripts.
Note that the non-interactive mode is not available for the master socket.
publish backend <backend>
Activates content switching to a backend instance. This is the reverse
operation of "unpublish backend" command. This command is restricted and can
only be issued on sockets configured for levels "operator" or "admin".
quit
Close the connection when in interactive mode.
@ -2842,6 +2847,13 @@ operator
increased. It also drops expert and experimental mode. See also "show cli
level".
unpublish backend <backend>
Marks the backend as unqualified for future traffic selection. In effect,
use_backend / default_backend rules which reference it are ignored and the
next content switching rules are evaluated. Contrary to disabled backends,
servers health checks remain active. This command is restricted and can only
be issued on sockets configured for levels "operator" or "admin".
user
Decrease the CLI level of the current CLI session to user. It can't be
increased. It also drops expert and experimental mode. See also "show cli
@ -3342,9 +3354,10 @@ show quic [<format>] [<filter>]
in the format will instead show a more detailed help message.
The final argument is used to restrict or extend the connection list. By
default, connections on closing or draining state are not displayed. Use the
extra argument "all" to include them in the output. It's also possible to
restrict to a single connection by specifying its hexadecimal address.
default, active frontend connections only are displayed. Use the extra
argument "clo" to list instead closing frontend connections, "be" for backend
connections or "all" for every categories. It's also possible to restrict to
a single connection by specifying its hexadecimal address.
show servers conn [<backend>]
Dump the current and idle connections state of the servers belonging to the

View File

@ -85,7 +85,8 @@ struct acme_ctx {
struct ist finalize;
struct ist certificate;
struct task *task;
struct mt_list el;
struct ebmb_node node;
char name[VAR_ARRAY];
};
#define ACME_EV_SCHED (1ULL << 0) /* scheduling wakeup */

View File

@ -125,8 +125,8 @@ struct activity {
unsigned int ctr2; // general purposee debug counter
#endif
char __pad[0]; // unused except to check remaining room
char __end[0] __attribute__((aligned(64))); // align size to 64.
};
char __end[0] THREAD_ALIGNED();
} THREAD_ALIGNED();
/* 256 entries for callers * callees should be highly sufficient (~45 seen usually) */
#define SCHED_ACT_HASH_BITS 8
@ -146,7 +146,7 @@ struct sched_activity {
uint64_t lkw_time; /* lock waiting time */
uint64_t lkd_time; /* locked time */
uint64_t mem_time; /* memory ops wait time */
};
} THREAD_ALIGNED();
#endif /* _HAPROXY_ACTIVITY_T_H */

View File

@ -366,7 +366,7 @@ static inline size_t applet_output_data(const struct appctx *appctx)
* This is useful when data have been read directly from the buffer. It is
* illegal to call this function with <len> causing a wrapping at the end of the
* buffer. It's the caller's responsibility to ensure that <len> is never larger
* than available ouput data.
* than available output data.
*
* This function is not HTX aware.
*/
@ -392,7 +392,7 @@ static inline void applet_reset_input(struct appctx *appctx)
co_skip(sc_oc(appctx_sc(appctx)), co_data(sc_oc(appctx_sc(appctx))));
}
/* Returns the amout of space available at the HTX output buffer (see applet_get_outbuf).
/* Returns the amount of space available at the HTX output buffer (see applet_get_outbuf).
*/
static inline size_t applet_htx_output_room(const struct appctx *appctx)
{
@ -402,7 +402,7 @@ static inline size_t applet_htx_output_room(const struct appctx *appctx)
return channel_recv_max(sc_ic(appctx_sc(appctx)));
}
/* Returns the amout of space available at the output buffer (see applet_get_outbuf).
/* Returns the amount of space available at the output buffer (see applet_get_outbuf).
*/
static inline size_t applet_output_room(const struct appctx *appctx)
{

View File

@ -46,6 +46,8 @@ int alloc_bind_address(struct sockaddr_storage **ss,
struct server *srv, struct proxy *be,
struct stream *s);
int be_reuse_mode(const struct proxy *be, const struct server *srv);
int64_t be_calculate_conn_hash(struct server *srv, struct stream *strm,
struct session *sess,
struct sockaddr_storage *src,
@ -83,10 +85,20 @@ static inline int be_usable_srv(struct proxy *be)
return be->srv_bck;
}
/* Returns true if <be> backend can be used as target to a switching rules. */
static inline int be_is_eligible(const struct proxy *be)
{
/* A disabled or unpublished backend cannot be selected for traffic.
* Note that STOPPED state is ignored as there is a risk of breaking
* requests during soft-stop.
*/
return !(be->flags & (PR_FL_DISABLED|PR_FL_BE_UNPUBLISHED));
}
/* set the time of last session on the backend */
static inline void be_set_sess_last(struct proxy *be)
{
if (be->be_counters.shared.tg[tgid - 1])
if (be->be_counters.shared.tg)
HA_ATOMIC_STORE(&be->be_counters.shared.tg[tgid - 1]->last_sess, ns_to_sec(now_ns));
}

View File

@ -40,6 +40,23 @@
#define DPRINTF(x...)
#endif
/* Let's make DEBUG_STRESS equal to zero if not set or not valid, or to
* 1 if set. This way it is always set and should be easy to use in "if ()"
* statements without requiring ifdefs, while remaining compatible with
* "#if DEBUG_STRESS > 0". We also force DEBUG_STRICT and DEBUG_STRICT_ACTION
* when stressed.
*/
#if !defined(DEBUG_STRESS)
# define DEBUG_STRESS 0
#elif DEBUG_STRESS != 0
# undef DEBUG_STRESS
# define DEBUG_STRESS 1 // make sure comparison >0 always works
# undef DEBUG_STRICT
# define DEBUG_STRICT 2 // enable BUG_ON
# undef DEBUG_STRICT_ACTION
# define DEBUG_STRICT_ACTION 3 // enable crash on match
#endif
#define DUMP_TRACE() do { extern void ha_backtrace_to_stderr(void); ha_backtrace_to_stderr(); } while (0)
/* First, let's try to handle some arch-specific crashing methods. We prefer
@ -407,6 +424,20 @@ extern __attribute__((__weak__)) struct debug_count __stop_dbg_cnt HA_SECTION_S
# define COUNT_IF_HOT(cond, ...) DISGUISE(cond)
#endif
/* turn BUG_ON_STRESS() into a real statement when DEBUG_STRESS is set,
* otherwise simply ignore it, at the risk of failing to notice if the
* condition would build at all. We don't really care if BUG_ON_STRESS
* doesn't always build, because it's meant to be used only in certain
* scenarios, possibly requiring certain combinations of options. We
* just want to be certain that the condition is not implemented at all
* when not used, so as to encourage developers to put a lot of them at
* zero cost.
*/
#if DEBUG_STRESS > 0
# define BUG_ON_STRESS(cond, ...) BUG_ON(cond, __VA_ARGS__)
#else
# define BUG_ON_STRESS(cond, ...) do { } while (0)
#endif
/* When not optimizing, clang won't remove that code, so only compile it in when optimizing */
#if defined(__GNUC__) && defined(__OPTIMIZE__)
@ -506,7 +537,7 @@ struct mem_stats {
size_t size;
struct ha_caller caller;
const void *extra; // extra info specific to this call (e.g. pool ptr)
} __attribute__((aligned(sizeof(void*))));
} ALIGNED(sizeof(void*));
#undef calloc
#define calloc(x,y) ({ \

View File

@ -54,6 +54,8 @@ enum cond_predicate {
CFG_PRED_OSSL_VERSION_ATLEAST, // "openssl_version_atleast"
CFG_PRED_OSSL_VERSION_BEFORE, // "openssl_version_before"
CFG_PRED_SSLLIB_NAME_STARTSWITH, // "ssllib_name_startswith"
CFG_PRED_AWSLC_API_ATLEAST, // "awslc_api_atleast"
CFG_PRED_AWSLC_API_BEFORE, // "awslc_api_before"
CFG_PRED_ENABLED, // "enabled"
};

View File

@ -140,7 +140,7 @@ int warnif_misplaced_tcp_req_sess(struct proxy *proxy, const char *file, int lin
int warnif_misplaced_tcp_req_cont(struct proxy *proxy, const char *file, int line, const char *arg, const char *arg2);
int warnif_misplaced_tcp_res_cont(struct proxy *proxy, const char *file, int line, const char *arg, const char *arg2);
int warnif_misplaced_quic_init(struct proxy *proxy, const char *file, int line, const char *arg, const char *arg2);
int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line);
int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, char **err);
int warnif_tcp_http_cond(const struct proxy *px, const struct acl_cond *cond);
int too_many_args_idx(int maxarg, int index, char **args, char **msg, int *err_code);
int too_many_args(int maxarg, char **args, char **msg, int *err_code);

View File

@ -31,6 +31,23 @@
#include <stdlib.h>
#endif
/* DEFVAL() returns either the second argument as-is, or <def> if absent. This
* is for use in macros arguments.
*/
#define DEFVAL(_def,...) _FIRST_ARG(NULL, ##__VA_ARGS__, (_def))
/* DEFNULL() returns either the argument as-is, or NULL if absent. This is for
* use in macros arguments.
*/
#define DEFNULL(...) DEFVAL(NULL, ##__VA_ARGS__)
/* DEFZERO() returns either the argument as-is, or 0 if absent. This is for
* use in macros arguments.
*/
#define DEFZERO(...) DEFVAL(0, ##__VA_ARGS__)
#define _FIRST_ARG(a, b, ...) b
/*
* Gcc before 3.0 needs [0] to declare a variable-size array
*/
@ -415,6 +432,13 @@
* for multi_threading, see THREAD_PAD() below. *
\*****************************************************************************/
/* Cache line size for alignment purposes. This value is incorrect for some
* Apple CPUs which have 128 bytes cache lines.
*/
#ifndef CACHELINE_SIZE
#define CACHELINE_SIZE 64
#endif
/* sets alignment for current field or variable */
#ifndef ALIGNED
#define ALIGNED(x) __attribute__((aligned(x)))
@ -438,12 +462,12 @@
#endif
#endif
/* sets alignment for current field or variable only when threads are enabled.
* Typically used to respect cache line alignment to avoid false sharing.
/* Sets alignment for current field or variable only when threads are enabled.
* When no parameters are provided, we align to the cache line size.
*/
#ifndef THREAD_ALIGNED
#ifdef USE_THREAD
#define THREAD_ALIGNED(x) __attribute__((aligned(x)))
#define THREAD_ALIGNED(...) ALIGNED(DEFVAL(CACHELINE_SIZE, ##__VA_ARGS__))
#else
#define THREAD_ALIGNED(x)
#endif
@ -476,13 +500,12 @@
#endif
#endif
/* add an optional alignment for next fields in a structure, only when threads
* are enabled. Typically used to respect cache line alignment to avoid false
* sharing.
/* Add an optional alignment for next fields in a structure, only when threads
* are enabled. When no parameters are provided, we align to the cache line size.
*/
#ifndef THREAD_ALIGN
#ifdef USE_THREAD
#define THREAD_ALIGN(x) union { } ALIGNED(x)
#define THREAD_ALIGN(...) union { } ALIGNED(DEFVAL(CACHELINE_SIZE, ##__VA_ARGS__))
#else
#define THREAD_ALIGN(x)
#endif
@ -507,7 +530,7 @@
/* add mandatory padding of the specified size between fields in a structure,
* This is used to avoid false sharing of cache lines for dynamically allocated
* structures which cannot guarantee alignment, or to ensure that the size of
* the struct remains consistent on architectures with different aligment
* the struct remains consistent on architectures with different alignment
* constraints
*/
#ifndef ALWAYS_PAD

View File

@ -145,7 +145,7 @@ enum {
CO_FL_WAIT_ROOM = 0x00000800, /* data sink is full */
CO_FL_WANT_SPLICING = 0x00001000, /* we wish to use splicing on the connection when possible */
/* unused: 0x00002000 */
CO_FL_SSL_NO_CACHED_INFO = 0x00002000, /* Don't use any cached information when creating a new SSL connection */
CO_FL_EARLY_SSL_HS = 0x00004000, /* We have early data pending, don't start SSL handshake yet */
CO_FL_EARLY_DATA = 0x00008000, /* At least some of the data are early data */
@ -212,13 +212,13 @@ static forceinline char *conn_show_flags(char *buf, size_t len, const char *deli
/* flags */
_(CO_FL_SAFE_LIST, _(CO_FL_IDLE_LIST, _(CO_FL_CTRL_READY,
_(CO_FL_REVERSED, _(CO_FL_ACT_REVERSING, _(CO_FL_OPT_MARK, _(CO_FL_OPT_TOS,
_(CO_FL_XPRT_READY, _(CO_FL_WANT_DRAIN, _(CO_FL_WAIT_ROOM, _(CO_FL_EARLY_SSL_HS,
_(CO_FL_XPRT_READY, _(CO_FL_WANT_DRAIN, _(CO_FL_WAIT_ROOM, _(CO_FL_SSL_NO_CACHED_INFO, _(CO_FL_EARLY_SSL_HS,
_(CO_FL_EARLY_DATA, _(CO_FL_SOCKS4_SEND, _(CO_FL_SOCKS4_RECV, _(CO_FL_SOCK_RD_SH,
_(CO_FL_SOCK_WR_SH, _(CO_FL_ERROR, _(CO_FL_FDLESS, _(CO_FL_WAIT_L4_CONN,
_(CO_FL_WAIT_L6_CONN, _(CO_FL_SEND_PROXY, _(CO_FL_ACCEPT_PROXY, _(CO_FL_ACCEPT_CIP,
_(CO_FL_SSL_WAIT_HS, _(CO_FL_PRIVATE, _(CO_FL_RCVD_PROXY, _(CO_FL_SESS_IDLE,
_(CO_FL_XPRT_TRACKED
))))))))))))))))))))))))))));
)))))))))))))))))))))))))))));
/* epilogue */
_(~0U);
return buf;
@ -476,7 +476,7 @@ struct xprt_ops {
void (*dump_info)(struct buffer *, const struct connection *);
/*
* Returns the value for various capabilities.
* Returns 0 if the capability is known, iwth the actual value in arg,
* Returns 0 if the capability is known, with the actual value in arg,
* or -1 otherwise
*/
int (*get_capability)(struct connection *connection, void *xprt_ctx, enum xprt_capabilities, void *arg);
@ -660,6 +660,7 @@ struct connection {
struct buffer name; /* Only used for passive reverse. Used as SNI when connection added to server idle pool. */
} reverse;
uint64_t sni_hash; /* Hash of the SNI. Used to cache the TLS session and try to reuse it. set to 0 is there is no SNI */
uint32_t term_evts_log; /* Termination events log: first 4 events reported from fd, handshake or xprt */
uint32_t mark; /* set network mark, if CO_FL_OPT_MARK is set */
uint8_t tos; /* set ip tos, if CO_FL_OPT_TOS is set */
@ -670,6 +671,7 @@ struct mux_proto_list {
enum proto_proxy_mode mode;
enum proto_proxy_side side;
const struct mux_ops *mux;
const char *alpn; /* Default alpn to set by default when the mux protocol is forced (optional, in binary form) */
struct list list;
};
@ -793,7 +795,7 @@ struct idle_conns {
struct mt_list toremove_conns;
struct task *cleanup_task;
__decl_thread(HA_SPINLOCK_T idle_conns_lock);
} THREAD_ALIGNED(64);
} THREAD_ALIGNED();
/* Termination events logs:

View File

@ -83,7 +83,7 @@ int conn_install_mux_be(struct connection *conn, void *ctx, struct session *sess
const struct mux_ops *force_mux_ops);
int conn_install_mux_chk(struct connection *conn, void *ctx, struct session *sess);
void conn_delete_from_tree(struct connection *conn, int thr, int permanent);
void conn_delete_from_tree(struct connection *conn, int thr);
void conn_init(struct connection *conn, void *target);
struct connection *conn_new(void *target);

View File

@ -66,7 +66,7 @@ struct counters_shared {
COUNTERS_SHARED;
struct {
COUNTERS_SHARED_TG;
} *tg[MAX_TGROUPS];
} **tg;
};
/*
@ -101,7 +101,7 @@ struct fe_counters_shared_tg {
struct fe_counters_shared {
COUNTERS_SHARED;
struct fe_counters_shared_tg *tg[MAX_TGROUPS];
struct fe_counters_shared_tg **tg;
};
/* counters used by listeners and frontends */
@ -160,7 +160,7 @@ struct be_counters_shared_tg {
struct be_counters_shared {
COUNTERS_SHARED;
struct be_counters_shared_tg *tg[MAX_TGROUPS];
struct be_counters_shared_tg **tg;
};
/* counters used by servers and backends */

View File

@ -43,11 +43,13 @@ void counters_be_shared_drop(struct be_counters_shared *counters);
*/
#define COUNTERS_SHARED_LAST_OFFSET(scounters, type, offset) \
({ \
unsigned long last = HA_ATOMIC_LOAD((type *)((char *)scounters[0] + offset));\
unsigned long last = 0; \
unsigned long now_seconds = ns_to_sec(now_ns); \
int it; \
\
for (it = 1; (it < global.nbtgroups && scounters[it]); it++) { \
if (scounters) \
last = HA_ATOMIC_LOAD((type *)((char *)scounters[0] + offset));\
for (it = 1; (it < global.nbtgroups && scounters); it++) { \
unsigned long cur = HA_ATOMIC_LOAD((type *)((char *)scounters[it] + offset));\
if ((now_seconds - cur) < (now_seconds - last)) \
last = cur; \
@ -74,7 +76,7 @@ void counters_be_shared_drop(struct be_counters_shared *counters);
uint64_t __ret = 0; \
int it; \
\
for (it = 0; (it < global.nbtgroups && scounters[it]); it++) \
for (it = 0; (it < global.nbtgroups && scounters); it++) \
__ret += rfunc((type *)((char *)scounters[it] + offset)); \
__ret; \
})
@ -94,7 +96,7 @@ void counters_be_shared_drop(struct be_counters_shared *counters);
uint64_t __ret = 0; \
int it; \
\
for (it = 0; (it < global.nbtgroups && scounters[it]); it++) \
for (it = 0; (it < global.nbtgroups && scounters); it++) \
__ret += rfunc(&scounters[it]->elem, arg1, arg2); \
__ret; \
})

View File

@ -202,7 +202,7 @@ struct fdtab {
#ifdef DEBUG_FD
unsigned int event_count; /* number of events reported */
#endif
} THREAD_ALIGNED(64);
} THREAD_ALIGNED();
/* polled mask, one bit per thread and per direction for each FD */
struct polled_mask {

View File

@ -31,7 +31,7 @@
ullong _freq_ctr_total_from_values(uint period, int pend, uint tick, ullong past, ullong curr);
ullong freq_ctr_total(const struct freq_ctr *ctr, uint period, int pend);
ullong freq_ctr_total_estimate(const struct freq_ctr *ctr, uint period, int pend);
int freq_ctr_overshoot_period(const struct freq_ctr *ctr, uint period, uint freq);
uint freq_ctr_overshoot_period(const struct freq_ctr *ctr, uint period, uint freq);
uint update_freq_ctr_period_slow(struct freq_ctr *ctr, uint period, uint inc);
/* Only usable during single threaded startup phase. */

View File

@ -233,6 +233,7 @@ struct global {
* than 255 arguments
*/
/* 2-bytes hole */
int est_fd_usage; /* rough estimate of reserved FDs (listeners, pollers etc) */
int cfg_curr_line; /* line number currently being parsed */
const char *cfg_curr_file; /* config file currently being parsed or NULL */
char *cfg_curr_section; /* config section name currently being parsed or NULL */
@ -260,6 +261,7 @@ struct global {
unsigned int req_count; /* request counter (HTTP or TCP session) for logs and unique_id */
int last_checks;
uint32_t anon_key;
int maxthrpertgroup; /* Maximum number of threads per thread group */
/* leave this at the end to make sure we don't share this cache line by accident */
ALWAYS_ALIGN(64);

View File

@ -255,6 +255,7 @@ struct hlua_patref_iterator_context {
struct hlua_patref *ref;
struct bref bref; /* back-reference from the pat_ref_elt being accessed
* during listing */
struct pat_ref_gen *gen; /* the generation we are iterating over */
};
#else /* USE_LUA */

View File

@ -184,6 +184,7 @@ enum {
PERSIST_TYPE_NONE = 0, /* no persistence */
PERSIST_TYPE_FORCE, /* force-persist */
PERSIST_TYPE_IGNORE, /* ignore-persist */
PERSIST_TYPE_BE_SWITCH, /* force-be-switch */
};
/* final results for http-request rules */

View File

@ -270,7 +270,7 @@ struct htx {
/* XXX 4 bytes unused */
/* Blocks representing the HTTP message itself */
char blocks[VAR_ARRAY] __attribute__((aligned(8)));
char blocks[VAR_ARRAY] ALIGNED(8);
};
#endif /* _HAPROXY_HTX_T_H */

View File

@ -186,7 +186,7 @@ struct bind_conf {
#endif
#ifdef USE_QUIC
struct quic_transport_params quic_params; /* QUIC transport parameters. */
struct quic_cc_algo *quic_cc_algo; /* QUIC control congestion algorithm */
const struct quic_cc_algo *quic_cc_algo; /* QUIC control congestion algorithm */
size_t max_cwnd; /* QUIC maximumu congestion control window size (kB) */
enum quic_sock_mode quic_mode; /* QUIC socket allocation strategy */
#endif
@ -204,6 +204,7 @@ struct bind_conf {
unsigned int backlog; /* if set, listen backlog */
int maxconn; /* maximum connections allowed on this listener */
int (*accept)(struct connection *conn); /* upper layer's accept() */
int tcp_ss; /* for TCP, Save SYN */
int level; /* stats access level (ACCESS_LVL_*) */
int severity_output; /* default severity output format in cli feedback messages */
short int nice; /* nice value to assign to the instantiated tasks */
@ -309,7 +310,7 @@ struct bind_kw_list {
struct accept_queue_ring {
uint32_t idx; /* (head << 16) | tail */
struct tasklet *tasklet; /* tasklet of the thread owning this ring */
struct connection *entry[ACCEPT_QUEUE_SIZE] __attribute((aligned(64)));
struct connection *entry[ACCEPT_QUEUE_SIZE] THREAD_ALIGNED();
};

View File

@ -231,7 +231,7 @@ const char *listener_state_str(const struct listener *l);
struct task *accept_queue_process(struct task *t, void *context, unsigned int state);
struct task *manage_global_listener_queue(struct task *t, void *context, unsigned int state);
extern struct accept_queue_ring accept_queue_rings[MAX_THREADS] __attribute__((aligned(64)));
extern struct accept_queue_ring accept_queue_rings[MAX_THREADS] THREAD_ALIGNED();
extern const char* li_status_st[LI_STATE_COUNT];
enum li_status get_li_status(struct listener *l);

View File

@ -41,6 +41,7 @@ struct qcc {
struct connection *conn;
uint64_t nb_sc; /* number of attached stream connectors */
uint64_t nb_hreq; /* number of in-progress http requests */
uint64_t tot_sc; /* total number of stream connectors seen since conn init */
uint32_t flags; /* QC_CF_* */
enum qcc_app_st app_st; /* application layer state */
int glitches; /* total number of glitches on this connection */

View File

@ -77,7 +77,8 @@ enum ssl_encryption_level_t {
#if defined(OPENSSL_IS_AWSLC)
#define OPENSSL_NO_DH
#define SSL_CTX_set1_sigalgs_list SSL_CTX_set1_sigalgs_list
#define SSL_CTX_set1_sigalgs_list SSL_CTX_set1_sigalgs_list
#define SSL_set_quic_early_data_enabled SSL_set_early_data_enabled
#endif

View File

@ -107,20 +107,34 @@ struct pat_ref {
struct list list; /* Used to chain refs. */
char *reference; /* The reference name. */
char *display; /* String displayed to identify the pattern origin. */
struct list head; /* The head of the list of struct pat_ref_elt. */
struct ceb_root *ceb_root; /* The tree where pattern reference elements are attached. */
struct ceb_root *gen_root; /* The tree mapping generation IDs to pattern reference elements */
struct list pat; /* The head of the list of struct pattern_expr. */
unsigned int flags; /* flags PAT_REF_*. */
unsigned int curr_gen; /* current generation number (anything below can be removed) */
unsigned int next_gen; /* next generation number (insertions use this one) */
/* We keep a cached pointer to the current generation for performance. */
struct {
struct pat_ref_gen *data;
unsigned int id;
} cached_gen;
int unique_id; /* Each pattern reference have unique id. */
unsigned long long revision; /* updated for each update */
unsigned long long entry_cnt; /* the total number of entries */
THREAD_ALIGN(64);
THREAD_ALIGN();
__decl_thread(HA_RWLOCK_T lock); /* Lock used to protect pat ref elements */
event_hdl_sub_list e_subs; /* event_hdl: pat_ref's subscribers list (atomically updated) */
};
/* This struct represents all the elements in a pattern reference generation. The tree
* is used most of the time, but we also maintain a list for when order matters.
*/
struct pat_ref_gen {
struct list head; /* The head of the list of struct pat_ref_elt. */
struct ceb_root *elt_root; /* The tree where pattern reference elements are attached. */
struct ceb_node gen_node; /* Linkage for the gen_root cebtree in struct pat_ref */
unsigned int gen_id;
};
/* This is a part of struct pat_ref. Each entry contains one pattern and one
* associated value as original string. All derivative forms (via exprs) are
* accessed from list_head or tree_head. Be careful, it's variable-sized!
@ -133,7 +147,7 @@ struct pat_ref_elt {
char *sample;
unsigned int gen_id; /* generation of pat_ref this was made for */
int line;
struct ceb_node node; /* Node to attach this element to its <pat_ref> ebtree. */
struct ceb_node node; /* Node to attach this element to its <pat_ref_gen> cebtree. */
const char pattern[0]; // const only to make sure nobody tries to free it.
};

View File

@ -189,8 +189,10 @@ struct pat_ref *pat_ref_new(const char *reference, const char *display, unsigned
struct pat_ref *pat_ref_newid(int unique_id, const char *display, unsigned int flags);
struct pat_ref_elt *pat_ref_find_elt(struct pat_ref *ref, const char *key);
struct pat_ref_elt *pat_ref_gen_find_elt(struct pat_ref *ref, unsigned int gen_id, const char *key);
struct pat_ref_elt *pat_ref_append(struct pat_ref *ref, const char *pattern, const char *sample, int line);
struct pat_ref_elt *pat_ref_append(struct pat_ref *ref, unsigned int gen, const char *pattern, const char *sample, int line);
struct pat_ref_elt *pat_ref_load(struct pat_ref *ref, unsigned int gen, const char *pattern, const char *sample, int line, char **err);
struct pat_ref_gen *pat_ref_gen_new(struct pat_ref *ref, unsigned int gen_id);
struct pat_ref_gen *pat_ref_gen_get(struct pat_ref *ref, unsigned int gen_id);
int pat_ref_push(struct pat_ref_elt *elt, struct pattern_expr *expr, int patflags, char **err);
int pat_ref_add(struct pat_ref *ref, const char *pattern, const char *sample, char **err);
int pat_ref_set(struct pat_ref *ref, const char *pattern, const char *sample, char **err);

View File

@ -63,7 +63,7 @@ struct pool_cache_head {
unsigned int tid; /* thread id, for debugging only */
struct pool_head *pool; /* assigned pool, for debugging only */
ulong fill_pattern; /* pattern used to fill the area on free */
} THREAD_ALIGNED(64);
} THREAD_ALIGNED();
/* This describes a pool registration, which is what was passed to
* create_pool() and that might have been merged with an existing pool.
@ -139,7 +139,7 @@ struct pool_head {
struct list regs; /* registrations: alt names for this pool */
/* heavily read-write part */
THREAD_ALIGN(64);
THREAD_ALIGN();
/* these entries depend on the pointer value, they're used to reduce
* the contention on fast-changing values. The alignment here is
@ -148,7 +148,7 @@ struct pool_head {
* just meant to shard elements and there are no per-free_list stats.
*/
struct {
THREAD_ALIGN(64);
THREAD_ALIGN();
struct pool_item *free_list; /* list of free shared objects */
unsigned int allocated; /* how many chunks have been allocated */
unsigned int used; /* how many chunks are currently in use */
@ -156,8 +156,8 @@ struct pool_head {
unsigned int failed; /* failed allocations (indexed by hash of TID) */
} buckets[CONFIG_HAP_POOL_BUCKETS];
struct pool_cache_head cache[MAX_THREADS] THREAD_ALIGNED(64); /* pool caches */
} __attribute__((aligned(64)));
struct pool_cache_head cache[MAX_THREADS] THREAD_ALIGNED(); /* pool caches */
} THREAD_ALIGNED();
#endif /* _HAPROXY_POOL_T_H */

View File

@ -160,6 +160,7 @@ struct protocol {
/* default I/O handler */
void (*default_iocb)(int fd); /* generic I/O handler (typically accept callback) */
int (*get_info)(struct connection *conn, long long int *info, int info_num); /* Callback to get connection level statistical counters */
int (*get_opt)(const struct connection *conn, int level, int optname, void *buf, int size); /* getsockopt(level:optname) into buf:size */
uint flags; /* flags describing protocol support (PROTO_F_*) */
uint nb_receivers; /* number of receivers (under proto_lock) */

View File

@ -247,6 +247,7 @@ enum PR_SRV_STATE_FILE {
#define PR_FL_IMPLICIT_REF 0x10 /* The default proxy is implicitly referenced by another proxy */
#define PR_FL_PAUSED 0x20 /* The proxy was paused at run time (reversible) */
#define PR_FL_CHECKED 0x40 /* The proxy configuration was fully checked (including postparsing checks) */
#define PR_FL_BE_UNPUBLISHED 0x80 /* The proxy cannot be targetted by content switching rules */
struct stream;
@ -304,7 +305,7 @@ struct error_snapshot {
struct proxy_per_tgroup {
struct queue queue;
struct lbprm_per_tgrp lbprm;
} THREAD_ALIGNED(64);
} THREAD_ALIGNED();
struct proxy {
enum obj_type obj_type; /* object type == OBJ_TYPE_PROXY */
@ -505,7 +506,7 @@ struct proxy {
EXTRA_COUNTERS(extra_counters_fe);
EXTRA_COUNTERS(extra_counters_be);
THREAD_ALIGN(64);
THREAD_ALIGN();
unsigned int queueslength; /* Sum of the length of each queue */
int served; /* # of active sessions currently being served */
int totpend; /* total number of pending connections on this instance (for stats) */

View File

@ -166,12 +166,12 @@ static inline int proxy_abrt_close(const struct proxy *px)
/* increase the number of cumulated connections received on the designated frontend */
static inline void proxy_inc_fe_conn_ctr(struct listener *l, struct proxy *fe)
{
if (fe->fe_counters.shared.tg[tgid - 1])
if (fe->fe_counters.shared.tg) {
_HA_ATOMIC_INC(&fe->fe_counters.shared.tg[tgid - 1]->cum_conn);
if (l && l->counters && l->counters->shared.tg[tgid - 1])
_HA_ATOMIC_INC(&l->counters->shared.tg[tgid - 1]->cum_conn);
if (fe->fe_counters.shared.tg[tgid - 1])
update_freq_ctr(&fe->fe_counters.shared.tg[tgid - 1]->conn_per_sec, 1);
}
if (l && l->counters && l->counters->shared.tg)
_HA_ATOMIC_INC(&l->counters->shared.tg[tgid - 1]->cum_conn);
HA_ATOMIC_UPDATE_MAX(&fe->fe_counters.cps_max,
update_freq_ctr(&fe->fe_counters._conn_per_sec, 1));
}
@ -179,12 +179,12 @@ static inline void proxy_inc_fe_conn_ctr(struct listener *l, struct proxy *fe)
/* increase the number of cumulated connections accepted by the designated frontend */
static inline void proxy_inc_fe_sess_ctr(struct listener *l, struct proxy *fe)
{
if (fe->fe_counters.shared.tg[tgid - 1])
if (fe->fe_counters.shared.tg) {
_HA_ATOMIC_INC(&fe->fe_counters.shared.tg[tgid - 1]->cum_sess);
if (l && l->counters && l->counters->shared.tg[tgid - 1])
_HA_ATOMIC_INC(&l->counters->shared.tg[tgid - 1]->cum_sess);
if (fe->fe_counters.shared.tg[tgid - 1])
update_freq_ctr(&fe->fe_counters.shared.tg[tgid - 1]->sess_per_sec, 1);
}
if (l && l->counters && l->counters->shared.tg)
_HA_ATOMIC_INC(&l->counters->shared.tg[tgid - 1]->cum_sess);
HA_ATOMIC_UPDATE_MAX(&fe->fe_counters.sps_max,
update_freq_ctr(&fe->fe_counters._sess_per_sec, 1));
}
@ -199,19 +199,19 @@ static inline void proxy_inc_fe_cum_sess_ver_ctr(struct listener *l, struct prox
http_ver > sizeof(fe->fe_counters.shared.tg[tgid - 1]->cum_sess_ver) / sizeof(*fe->fe_counters.shared.tg[tgid - 1]->cum_sess_ver))
return;
if (fe->fe_counters.shared.tg[tgid - 1])
if (fe->fe_counters.shared.tg)
_HA_ATOMIC_INC(&fe->fe_counters.shared.tg[tgid - 1]->cum_sess_ver[http_ver - 1]);
if (l && l->counters && l->counters->shared.tg[tgid - 1])
if (l && l->counters && l->counters->shared.tg && l->counters->shared.tg[tgid - 1])
_HA_ATOMIC_INC(&l->counters->shared.tg[tgid - 1]->cum_sess_ver[http_ver - 1]);
}
/* increase the number of cumulated streams on the designated backend */
static inline void proxy_inc_be_ctr(struct proxy *be)
{
if (be->be_counters.shared.tg[tgid - 1])
if (be->be_counters.shared.tg) {
_HA_ATOMIC_INC(&be->be_counters.shared.tg[tgid - 1]->cum_sess);
if (be->be_counters.shared.tg[tgid - 1])
update_freq_ctr(&be->be_counters.shared.tg[tgid - 1]->sess_per_sec, 1);
}
HA_ATOMIC_UPDATE_MAX(&be->be_counters.sps_max,
update_freq_ctr(&be->be_counters._sess_per_sec, 1));
}
@ -226,12 +226,12 @@ static inline void proxy_inc_fe_req_ctr(struct listener *l, struct proxy *fe,
if (http_ver >= sizeof(fe->fe_counters.shared.tg[tgid - 1]->p.http.cum_req) / sizeof(*fe->fe_counters.shared.tg[tgid - 1]->p.http.cum_req))
return;
if (fe->fe_counters.shared.tg[tgid - 1])
if (fe->fe_counters.shared.tg) {
_HA_ATOMIC_INC(&fe->fe_counters.shared.tg[tgid - 1]->p.http.cum_req[http_ver]);
if (l && l->counters && l->counters->shared.tg[tgid - 1])
_HA_ATOMIC_INC(&l->counters->shared.tg[tgid - 1]->p.http.cum_req[http_ver]);
if (fe->fe_counters.shared.tg[tgid - 1])
update_freq_ctr(&fe->fe_counters.shared.tg[tgid - 1]->req_per_sec, 1);
}
if (l && l->counters && l->counters->shared.tg)
_HA_ATOMIC_INC(&l->counters->shared.tg[tgid - 1]->p.http.cum_req[http_ver]);
HA_ATOMIC_UPDATE_MAX(&fe->fe_counters.p.http.rps_max,
update_freq_ctr(&fe->fe_counters.p.http._req_per_sec, 1));
}

View File

@ -35,13 +35,13 @@
#define QUIC_CC_INFINITE_SSTHESH ((uint32_t)-1)
extern struct quic_cc_algo quic_cc_algo_nr;
extern struct quic_cc_algo quic_cc_algo_cubic;
extern struct quic_cc_algo quic_cc_algo_bbr;
extern struct quic_cc_algo *default_quic_cc_algo;
extern const struct quic_cc_algo quic_cc_algo_nr;
extern const struct quic_cc_algo quic_cc_algo_cubic;
extern const struct quic_cc_algo quic_cc_algo_bbr;
extern const struct quic_cc_algo *default_quic_cc_algo;
/* Fake algorithm with its fixed window */
extern struct quic_cc_algo quic_cc_algo_nocc;
extern const struct quic_cc_algo quic_cc_algo_nocc;
extern unsigned long long last_ts;
@ -90,7 +90,7 @@ enum quic_cc_algo_type {
struct quic_cc {
/* <conn> is there only for debugging purpose. */
struct quic_conn *qc;
struct quic_cc_algo *algo;
const struct quic_cc_algo *algo;
uint32_t priv[144];
};

View File

@ -35,7 +35,7 @@
#include <haproxy/quic_loss.h>
#include <haproxy/thread.h>
void quic_cc_init(struct quic_cc *cc, struct quic_cc_algo *algo, struct quic_conn *qc);
void quic_cc_init(struct quic_cc *cc, const struct quic_cc_algo *algo, struct quic_conn *qc);
void quic_cc_event(struct quic_cc *cc, struct quic_cc_event *ev);
void quic_cc_state_trace(struct buffer *buf, const struct quic_cc *cc);
@ -83,7 +83,7 @@ static inline void *quic_cc_priv(const struct quic_cc *cc)
* which is true for an IPv4 path, if not false for an IPv6 path.
*/
static inline void quic_cc_path_init(struct quic_cc_path *path, int ipv4, unsigned long max_cwnd,
struct quic_cc_algo *algo,
const struct quic_cc_algo *algo,
struct quic_conn *qc)
{
unsigned int max_dgram_sz;

View File

@ -24,6 +24,12 @@ struct quic_cid {
unsigned char len; /* size of QUIC CID */
};
/* Determines whether a CID is used for frontend or backend connections. */
enum quic_cid_side {
QUIC_CID_SIDE_FE,
QUIC_CID_SIDE_BE
};
/* QUIC connection id attached to a QUIC connection.
*
* This structure is used to match received packets DCIDs with the
@ -34,11 +40,12 @@ struct quic_connection_id {
uint64_t retire_prior_to;
unsigned char stateless_reset_token[QUIC_STATELESS_RESET_TOKEN_LEN];
struct ebmb_node node; /* node for receiver tree, cid.data as key */
struct quic_cid cid; /* CID data */
struct ebmb_node node; /* node for receiver tree, cid.data as key */
struct quic_cid cid; /* CID data */
struct quic_conn *qc; /* QUIC connection using this CID */
uint tid; /* Attached Thread ID for the connection. */
struct quic_conn *qc; /* QUIC connection using this CID */
uint tid; /* Attached Thread ID for the connection. */
enum quic_cid_side side; /* side where this CID is used */
};
#endif /* _HAPROXY_QUIC_CID_T_H */

View File

@ -15,12 +15,19 @@
#include <haproxy/quic_rx-t.h>
#include <haproxy/proto_quic.h>
extern struct quic_cid_tree *quic_cid_trees;
extern struct quic_cid_tree *quic_fe_cid_trees;
extern struct quic_cid_tree *quic_be_cid_trees;
struct quic_connection_id *new_quic_cid(struct eb_root *root,
struct quic_conn *qc,
const struct quic_cid *orig,
const struct sockaddr_storage *addr);
struct quic_connection_id *quic_cid_alloc(enum quic_cid_side side);
int quic_cid_generate_random(struct quic_connection_id *conn_id);
int quic_cid_generate_from_hash(struct quic_connection_id *conn_id, uint64_t hash64);
int quic_cid_derive_from_odcid(struct quic_connection_id *conn_id,
const struct quic_cid *orig,
const struct sockaddr_storage *addr);
void quic_cid_register_seq_num(struct quic_connection_id *conn_id,
struct quic_conn *qc);
int quic_cid_insert(struct quic_connection_id *conn_id, int *new_tid);
int quic_cmp_cid_conn(const unsigned char *cid, size_t cid_len,
@ -75,25 +82,18 @@ static inline uchar quic_cid_tree_idx(const struct quic_cid *cid)
return _quic_cid_tree_idx(cid->data);
}
/* Insert <conn_id> into global CID tree. Do not check if value is already
* present in the tree. As such, it should not be used for the first DCID of a
* connection instance.
*/
static inline void _quic_cid_insert(struct quic_connection_id *conn_id)
/* Returns the tree instance responsible for <conn_id> storage. */
static inline struct quic_cid_tree *quic_cid_get_tree(const struct quic_connection_id *conn_id)
{
const uchar idx = quic_cid_tree_idx(&conn_id->cid);
struct quic_cid_tree *tree = &quic_cid_trees[idx];
HA_RWLOCK_WRLOCK(QC_CID_LOCK, &tree->lock);
ebmb_insert(&tree->root, &conn_id->node, conn_id->cid.len);
HA_RWLOCK_WRUNLOCK(QC_CID_LOCK, &tree->lock);
const int tree_idx = quic_cid_tree_idx(&conn_id->cid);
return conn_id->side == QUIC_CID_SIDE_FE ?
&quic_fe_cid_trees[tree_idx] : &quic_be_cid_trees[tree_idx];
}
/* Remove <conn_id> from global CID tree as a thread-safe operation. */
static inline void quic_cid_delete(struct quic_connection_id *conn_id)
{
const uchar idx = quic_cid_tree_idx(&conn_id->cid);
struct quic_cid_tree __maybe_unused *tree = &quic_cid_trees[idx];
struct quic_cid_tree __maybe_unused *tree = quic_cid_get_tree(conn_id);
HA_RWLOCK_WRLOCK(QC_CID_LOCK, &tree->lock);
ebmb_delete(&conn_id->node);

View File

@ -292,9 +292,13 @@ struct qcc_app_ops;
size_t max_udp_payload; \
/* First DCID used by client on its Initial packet. */ \
struct quic_cid odcid; \
/* DCID of our endpoint - not updated when a new DCID is used */ \
/* Peer chosen CID, used as dest for packets sent from our endpoint \
* - not updated when a new DCID is used \
*/ \
struct quic_cid dcid; \
/* first SCID of our endpoint - not updated when a new SCID is used */ \
/* Local CID used to dispatch received datagrams to this endpoint \
* - not updated when a new SCID is used \
*/ \
struct quic_cid scid; \
/* tree of quic_connection_id - used to match a received packet DCID \
* with a connection \
@ -430,7 +434,7 @@ struct quic_conn_closed {
#define QUIC_FL_CONN_NEED_POST_HANDSHAKE_FRMS (1U << 2) /* HANDSHAKE_DONE must be sent */
#define QUIC_FL_CONN_IS_BACK (1U << 3) /* conn used on backend side */
#define QUIC_FL_CONN_ACCEPT_REGISTERED (1U << 4)
#define QUIC_FL_CONN_UDP_GSO_EIO (1U << 5) /* GSO disabled due to a EIO occured on same listener */
#define QUIC_FL_CONN_UDP_GSO_EIO (1U << 5) /* GSO disabled due to a EIO occurred on same listener */
#define QUIC_FL_CONN_IDLE_TIMER_RESTARTED_AFTER_READ (1U << 6)
#define QUIC_FL_CONN_RETRANS_NEEDED (1U << 7)
#define QUIC_FL_CONN_RETRANS_OLD_DATA (1U << 8) /* retransmission in progress for probing with already sent data */
@ -486,13 +490,14 @@ static forceinline char *qc_show_flags(char *buf, size_t len, const char *delim,
_(QUIC_FL_CONN_PEER_VALIDATED_ADDR,
_(QUIC_FL_CONN_NO_TOKEN_RCVD,
_(QUIC_FL_CONN_SCID_RECEIVED,
_(QUIC_FL_CONN_XPRT_CLOSED,
_(QUIC_FL_CONN_TO_KILL,
_(QUIC_FL_CONN_TX_TP_RECEIVED,
_(QUIC_FL_CONN_FINALIZED,
_(QUIC_FL_CONN_EXP_TIMER,
_(QUIC_FL_CONN_CLOSING,
_(QUIC_FL_CONN_DRAINING,
_(QUIC_FL_CONN_IMMEDIATE_CLOSE)))))))))))))))))))))))))));
_(QUIC_FL_CONN_IMMEDIATE_CLOSE))))))))))))))))))))))))))));
/* epilogue */
_(~0U);
return buf;

View File

@ -64,14 +64,15 @@ struct task *quic_conn_app_io_cb(struct task *t, void *context, unsigned int sta
void quic_conn_closed_err_count_inc(struct quic_conn *qc, struct quic_frame *frm);
int qc_h3_request_reject(struct quic_conn *qc, uint64_t id);
struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4,
struct quic_cid *dcid, struct quic_cid *scid,
struct quic_conn *qc_new_conn(void *target,
const struct quic_rx_packet *initial_pkt,
const struct quic_cid *token_odcid,
struct connection *connection,
struct quic_connection_id *conn_id,
struct sockaddr_storage *local_addr,
struct sockaddr_storage *peer_addr,
int token, void *owner);
int quic_build_post_handshake_frames(struct quic_conn *qc);
struct sockaddr_storage *peer_addr);
int quic_build_post_handshake_frames(struct quic_conn *qc,
struct list *to_frms_list);
const struct quic_version *qc_supported_version(uint32_t version);
int quic_peer_validated_addr(struct quic_conn *qc);
void qc_set_timer(struct quic_conn *qc);
@ -81,6 +82,9 @@ void qc_idle_timer_rearm(struct quic_conn *qc, int read, int arm_ack);
void qc_check_close_on_released_mux(struct quic_conn *qc);
int quic_stateless_reset_token_cpy(unsigned char *pos, size_t len,
const unsigned char *salt, size_t saltlen);
int quic_reuse_srv_params(struct quic_conn *qc,
const unsigned char *alpn,
const struct quic_early_transport_params *etps);
/* Returns true if <qc> is used on the backed side (as a client). */
static inline int qc_is_back(const struct quic_conn *qc)
@ -88,6 +92,12 @@ static inline int qc_is_back(const struct quic_conn *qc)
return qc->flags & QUIC_FL_CONN_IS_BACK;
}
static inline enum quic_cid_side qc_cid_side(const struct quic_conn *qc)
{
return !(qc->flags & QUIC_FL_CONN_IS_BACK) ?
QUIC_CID_SIDE_FE : QUIC_CID_SIDE_BE;
}
/* Free the CIDs attached to <conn> QUIC connection. */
static inline void free_quic_conn_cids(struct quic_conn *conn)
{

View File

@ -161,7 +161,10 @@ struct qf_crypto {
struct qf_new_token {
uint64_t len;
unsigned char data[QUIC_TOKEN_LEN];
/* Used only to send data */
unsigned char w_data[QUIC_TOKEN_LEN];
/* Used only to receive data */
const unsigned char *r_data;
};
struct qf_stream {

View File

@ -49,6 +49,7 @@ int qc_snd_buf(struct quic_conn *qc, const struct buffer *buf, size_t count,
int flags, uint16_t gso_size);
int qc_rcv_buf(struct quic_conn *qc);
void quic_conn_sock_fd_iocb(int fd);
void quic_conn_closed_sock_fd_iocb(int fd);
void qc_alloc_fd(struct quic_conn *qc, const struct sockaddr_storage *src,
const struct sockaddr_storage *dst);

View File

@ -17,5 +17,7 @@
#include <haproxy/pool-t.h>
extern struct pool_head *pool_head_quic_ssl_sock_ctx;
extern const char *default_quic_ciphersuites;
extern const char *default_quic_curves;
#endif /* _HAPROXY_QUIC_SSL_T_H */

View File

@ -81,7 +81,12 @@ static inline const char *quic_ssl_early_data_status_str(const SSL *ssl)
}
#endif
}
#else
#else /* !HAVE_SSL_0RTT_QUIC */
static inline int qc_ssl_eary_data_accepted(const SSL *ssl)
{
return 0;
}
static inline const char *quic_ssl_early_data_status_str(const SSL *ssl)
{
return "NOT_SUPPORTED";

View File

@ -112,6 +112,18 @@ struct quic_transport_params {
struct tp_version_information version_information;
};
/* Transport parameters to be saved for 0-RTT sessions. */
struct quic_early_transport_params {
uint64_t max_udp_payload_size;
uint64_t active_connection_id_limit;
uint64_t initial_max_data;
uint64_t initial_max_stream_data_bidi_local;
uint64_t initial_max_stream_data_bidi_remote;
uint64_t initial_max_stream_data_uni;
uint64_t initial_max_streams_bidi;
uint64_t initial_max_streams_uni;
};
/* Return type for QUIC TP decode function */
enum quic_tp_dec_err {
QUIC_TP_DEC_ERR_NONE = 0, /* no error */

View File

@ -18,7 +18,13 @@ int quic_transport_params_encode(unsigned char *buf,
int quic_transport_params_store(struct quic_conn *conn, int server,
const unsigned char *buf,
const unsigned char *end);
const unsigned char *end, int edata_accepted);
void qc_early_transport_params_cpy(struct quic_conn *qc,
struct quic_early_transport_params *e,
struct quic_transport_params *p);
void qc_early_transport_params_reuse(struct quic_conn *qc,
struct quic_transport_params *p,
const struct quic_early_transport_params *e);
int qc_lstnr_params_init(struct quic_conn *qc,
const struct quic_transport_params *listener_params,
@ -123,5 +129,23 @@ static inline void quic_transport_params_dump(struct buffer *b,
quic_tp_version_info_dump(b, &p->version_information, local);
}
static inline void quic_early_transport_params_dump(struct buffer *b,
const struct quic_conn *qc,
const struct quic_early_transport_params *p)
{
chunk_appendf(b, " mudp_payload_sz=%llu", (ull)p->max_udp_payload_size);
chunk_appendf(b, " act_cid_limit=%llu\n", (ull)p->active_connection_id_limit);
chunk_appendf(b, " md=%llu", (ull)p->initial_max_data);
chunk_appendf(b, " msd_bidi_l=%llu",
(ull)p->initial_max_stream_data_bidi_local);
chunk_appendf(b, " msd_bidi_r=%llu",
(ull)p->initial_max_stream_data_bidi_remote);
chunk_appendf(b, " msd_uni=%llu",
(ull)p->initial_max_stream_data_uni);
chunk_appendf(b, " ms_bidi=%llu", (ull)p->initial_max_streams_bidi);
chunk_appendf(b, " ms_uni=%llu\n", (ull)p->initial_max_streams_uni);
}
#endif /* USE_QUIC */
#endif /* _HAPROXY_QUIC_TP_H */

View File

@ -100,5 +100,6 @@ struct quic_rx_crypto_frm {
#define QUIC_EV_CONN_SSL_COMPAT (1ULL << 51)
#define QUIC_EV_CONN_BIND_TID (1ULL << 52)
#define QUIC_EV_CONN_RELEASE_RCD (1ULL << 53)
#define QUIC_EV_EARLY_TRANSP_PARAMS (1ULL << 54)
#endif /* _HAPROXY_QUIC_TRACE_T_H */

View File

@ -5,7 +5,7 @@
#include <haproxy/api-t.h>
/* Counter which can be used to measure data amount accross several buffers. */
/* Counter which can be used to measure data amount across several buffers. */
struct bdata_ctr {
uint64_t tot; /* sum of data present in all underlying buffers */
uint8_t bcnt; /* current number of allocated underlying buffers */

View File

@ -33,11 +33,12 @@
/* Bit values for receiver->flags */
#define RX_F_BOUND 0x00000001 /* receiver already bound */
#define RX_F_INHERITED 0x00000002 /* inherited FD from the parent process (fd@) or duped from another local receiver */
#define RX_F_INHERITED_FD 0x00000002 /* inherited FD from the parent process (fd@) */
#define RX_F_MWORKER 0x00000004 /* keep the FD open in the master but close it in the children */
#define RX_F_MUST_DUP 0x00000008 /* this receiver's fd must be dup() from a reference; ignore socket-level ops here */
#define RX_F_NON_SUSPENDABLE 0x00000010 /* this socket cannot be suspended hence must always be unbound */
#define RX_F_PASS_PKTINFO 0x00000020 /* pass pktinfo in received messages */
#define RX_F_INHERITED_SOCK 0x00000040 /* inherited sock that could be duped from another local receiver */
/* Bit values for rx_settings->options */
#define RX_O_FOREIGN 0x00000001 /* receives on foreign addresses */
@ -63,9 +64,8 @@ struct rx_settings {
struct shard_info {
uint nbgroups; /* number of groups in this shard (=#rx); Zero = unused. */
uint nbthreads; /* number of threads in this shard (>=nbgroups) */
ulong tgroup_mask; /* bitmask of thread groups having a member here */
struct receiver *ref; /* first one, reference for FDs to duplicate */
struct receiver *members[MAX_TGROUPS]; /* all members of the shard (one per thread group) */
struct receiver **members; /* all members of the shard (one per thread group) */
};
/* This describes a receiver with all its characteristics (address, options, etc) */

View File

@ -130,11 +130,11 @@ struct ring_wait_cell {
struct ring_storage {
size_t size; // storage size
size_t rsvd; // header length (used for file-backed maps)
THREAD_ALIGN(64);
THREAD_ALIGN();
size_t tail; // storage tail
THREAD_ALIGN(64);
THREAD_ALIGN();
size_t head; // storage head
THREAD_ALIGN(64);
THREAD_ALIGN();
char area[0]; // storage area begins immediately here
};
@ -149,7 +149,7 @@ struct ring {
/* keep the queue in a separate cache line below */
struct {
THREAD_ALIGN(64);
THREAD_ALIGN();
struct ring_wait_cell *ptr;
} queue[RING_WAIT_QUEUES + 1]; // wait queue + 1 spacer
};

View File

@ -63,6 +63,7 @@ int smp_expr_output_type(struct sample_expr *expr);
int c_none(struct sample *smp);
int c_pseudo(struct sample *smp);
int smp_dup(struct sample *smp);
int sample_check_arg_base64(struct arg *arg, char **err);
/*
* This function just apply a cast on sample. It returns 0 if the cast is not

View File

@ -276,6 +276,9 @@ struct srv_per_thread {
struct ceb_root *idle_conns; /* Shareable idle connections */
struct ceb_root *safe_conns; /* Safe idle connections */
struct ceb_root *avail_conns; /* Connections in use, but with still new streams available */
#ifdef USE_QUIC
struct ist quic_retry_token;
#endif
};
/* Each server will have one occurrence of this structure per thread group */
@ -291,7 +294,7 @@ struct srv_per_tgroup {
struct eb_root *lb_tree; /* For LB algos with split between thread groups, the tree to be used, for each group */
unsigned npos, lpos; /* next and last positions in the LB tree, protected by LB lock */
unsigned rweight; /* remainder of weight in the current LB tree */
} THREAD_ALIGNED(64);
} THREAD_ALIGNED();
/* Configure the protocol selection for websocket */
enum __attribute__((__packed__)) srv_ws_mode {
@ -322,6 +325,9 @@ enum renegotiate_mode {
struct path_parameters {
__decl_thread(HA_RWLOCK_T param_lock);
char nego_alpn[MAX_ALPN_SIZE];
#ifdef USE_QUIC
struct quic_early_transport_params tps;
#endif
};
struct proxy;
@ -390,7 +396,7 @@ struct server {
/* The elements below may be changed on every single request by any
* thread, and generally at the same time.
*/
THREAD_ALIGN(64);
THREAD_ALIGN();
struct eb32_node idle_node; /* When to next do cleanup in the idle connections */
unsigned int curr_idle_conns; /* Current number of orphan idling connections, both the idle and the safe lists */
unsigned int curr_idle_nb; /* Current number of connections in the idle list */
@ -408,7 +414,7 @@ struct server {
/* Element below are usd by LB algorithms and must be doable in
* parallel to other threads reusing connections above.
*/
THREAD_ALIGN(64);
THREAD_ALIGN();
__decl_thread(HA_SPINLOCK_T lock); /* may enclose the proxy's lock, must not be taken under */
union {
struct eb32_node lb_node; /* node used for tree-based load balancing */
@ -422,7 +428,7 @@ struct server {
};
/* usually atomically updated by any thread during parsing or on end of request */
THREAD_ALIGN(64);
THREAD_ALIGN();
int cur_sess; /* number of currently active sessions (including syn_sent) */
int served; /* # of active sessions currently being served (ie not pending) */
int consecutive_errors; /* current number of consecutive errors */
@ -430,7 +436,7 @@ struct server {
struct be_counters counters; /* statistics counters */
/* Below are some relatively stable settings, only changed under the lock */
THREAD_ALIGN(64);
THREAD_ALIGN();
struct eb_root *lb_tree; /* we want to know in what tree the server is */
struct tree_occ *lb_nodes; /* lb_nodes_tot * struct tree_occ */
@ -479,7 +485,7 @@ struct server {
unsigned char *ptr;
int size;
int allocated_size;
char *sni; /* SNI used for the session */
uint64_t sni_hash; /* Hash of the SNI used for the session */
__decl_thread(HA_RWLOCK_T sess_lock);
} * reused_sess;
@ -508,6 +514,8 @@ struct server {
} ssl_ctx;
#ifdef USE_QUIC
struct quic_transport_params quic_params; /* QUIC transport parameters */
const struct quic_cc_algo *quic_cc_algo; /* QUIC control congestion algorithm */
size_t quic_max_cwnd; /* QUIC maximum congestion control window size (kB) */
#endif
struct path_parameters path_params; /* Connection parameters for that server */
struct resolv_srvrq *srvrq; /* Pointer representing the DNS SRV requeest, if any */

View File

@ -207,7 +207,7 @@ static inline void server_index_id(struct proxy *px, struct server *srv)
/* increase the number of cumulated streams on the designated server */
static inline void srv_inc_sess_ctr(struct server *s)
{
if (s->counters.shared.tg[tgid - 1]) {
if (s->counters.shared.tg) {
_HA_ATOMIC_INC(&s->counters.shared.tg[tgid - 1]->cum_sess);
update_freq_ctr(&s->counters.shared.tg[tgid - 1]->sess_per_sec, 1);
}
@ -218,7 +218,7 @@ static inline void srv_inc_sess_ctr(struct server *s)
/* set the time of last session on the designated server */
static inline void srv_set_sess_last(struct server *s)
{
if (s->counters.shared.tg[tgid - 1])
if (s->counters.shared.tg)
HA_ATOMIC_STORE(&s->counters.shared.tg[tgid - 1]->last_sess, ns_to_sec(now_ns));
}

View File

@ -46,6 +46,7 @@ struct connection *sock_accept_conn(struct listener *l, int *status);
void sock_accept_iocb(int fd);
void sock_conn_ctrl_init(struct connection *conn);
void sock_conn_ctrl_close(struct connection *conn);
int sock_conn_get_opt(const struct connection *conn, int level, int optname, void *buf, int size);
void sock_conn_iocb(int fd);
int sock_conn_check(struct connection *conn);
int sock_drain(struct connection *conn);

View File

@ -89,7 +89,6 @@ struct ckch_store {
struct list ckch_inst; /* list of ckch_inst which uses this ckch_node */
struct list crtlist_entry; /* list of entries which use this store */
struct ckch_conf conf;
struct task *acme_task;
struct ebmb_node node;
char path[VAR_ARRAY];
};

View File

@ -254,7 +254,7 @@ struct ssl_keylog {
#define SSL_SOCK_F_KTLS_SEND (1 << 2) /* kTLS send is configured on that socket */
#define SSL_SOCK_F_KTLS_RECV (1 << 3) /* kTLS receive is configure on that socket */
#define SSL_SOCK_F_CTRL_SEND (1 << 4) /* We want to send a kTLS control message for that socket */
#define SSL_SOCK_F_HAS_ALPN (1 << 5) /* An ALPN has been negociated */
#define SSL_SOCK_F_HAS_ALPN (1 << 5) /* An ALPN has been negotiated */
struct ssl_sock_ctx {
struct connection *conn;

View File

@ -30,6 +30,7 @@
#include <haproxy/proxy-t.h>
#include <haproxy/quic_conn-t.h>
#include <haproxy/ssl_sock-t.h>
#include <haproxy/stats.h>
#include <haproxy/thread.h>
extern struct list tlskeys_reference;
@ -57,6 +58,7 @@ extern struct pool_head *pool_head_ssl_keylog_str;
extern struct list openssl_providers;
extern struct stats_module ssl_stats_module;
uint64_t ssl_sock_sni_hash(const struct ist sni);
int ssl_sock_prep_ctx_and_inst(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
SSL_CTX *ctx, struct ckch_inst *ckch_inst, char **err);
int ssl_sock_prep_srv_ctx_and_inst(const struct server *srv, SSL_CTX *ctx,
@ -71,7 +73,7 @@ int ssl_sock_get_alpn(const struct connection *conn, void *xprt_ctx,
const char **str, int *len);
int ssl_bio_and_sess_init(struct connection *conn, SSL_CTX *ssl_ctx,
SSL **ssl, BIO **bio, BIO_METHOD *bio_meth, void *ctx);
void ssl_sock_srv_try_reuse_sess(struct ssl_sock_ctx *ctx, struct server *srv);
int ssl_sock_srv_try_reuse_sess(struct ssl_sock_ctx *ctx, struct server *srv);
const char *ssl_sock_get_sni(struct connection *conn);
const char *ssl_sock_get_cert_sig(struct connection *conn);
const char *ssl_sock_get_cipher_name(struct connection *conn);
@ -89,6 +91,7 @@ unsigned int ssl_sock_get_verify_result(struct connection *conn);
void ssl_sock_update_counters(SSL *ssl,
struct ssl_counters *counters,
struct ssl_counters *counters_px, int backend);
void ssl_sock_handle_hs_error(struct connection *conn);
#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
int ssl_sock_update_tlskey_ref(struct tls_keys_ref *ref,
struct buffer *tlskey);
@ -241,6 +244,30 @@ static inline struct connection *ssl_sock_get_conn(const SSL *s, struct ssl_sock
return ret;
}
/* Set at <counters> and <counters_px> addresses the SSL statistical counters */
static inline void ssl_sock_get_stats_counters(struct connection *conn,
struct ssl_counters **counters,
struct ssl_counters **counters_px)
{
switch (obj_type(conn->target)) {
case OBJ_TYPE_LISTENER: {
struct listener *li = __objt_listener(conn->target);
*counters = EXTRA_COUNTERS_GET(li->extra_counters, &ssl_stats_module);
*counters_px = EXTRA_COUNTERS_GET(li->bind_conf->frontend->extra_counters_fe,
&ssl_stats_module);
break;
}
case OBJ_TYPE_SERVER: {
struct server *srv = __objt_server(conn->target);
*counters = EXTRA_COUNTERS_GET(srv->extra_counters, &ssl_stats_module);
*counters_px = EXTRA_COUNTERS_GET(srv->proxy->extra_counters_be,
&ssl_stats_module);
break;
}
default:
break;
}
}
#endif /* USE_OPENSSL */
#endif /* _HAPROXY_SSL_SOCK_H */

View File

@ -57,6 +57,9 @@ const char *nid2nist(int nid);
const char *sigalg2str(int sigalg);
const char *curveid2str(int curve_id);
int aes_process(struct buffer *data, struct buffer *nonce, struct buffer *key, int key_size,
struct buffer *aead_tag, struct buffer *aad, struct buffer *out, int decrypt, int gcm);
#endif /* _HAPROXY_SSL_UTILS_H */
#endif /* USE_OPENSSL */

View File

@ -15,7 +15,7 @@ enum stfile_domain {
};
#define SHM_STATS_FILE_VER_MAJOR 1
#define SHM_STATS_FILE_VER_MINOR 1
#define SHM_STATS_FILE_VER_MINOR 2
#define SHM_STATS_FILE_HEARTBEAT_TIMEOUT 60 /* passed this delay (seconds) process which has not
* sent heartbeat will be considered down
@ -64,9 +64,9 @@ struct shm_stats_file_hdr {
*/
struct shm_stats_file_object {
char guid[GUID_MAX_LEN + 1];
uint8_t tgid; // thread group ID from 1 to 64
uint16_t tgid; // thread group ID
uint8_t type; // SHM_STATS_FILE_OBJECT_TYPE_* to know how to handle object.data
ALWAYS_PAD(6); // 6 bytes hole, ensure it remains the same size 32 vs 64 bits arch
ALWAYS_PAD(5); // 5 bytes hole, ensure it remains the same size 32 vs 64 bits arch
uint64_t users; // bitfield that corresponds to users of the object (see shm_stats_file_hdr slots)
/* as the struct may hold any of the types described here, let's make it
* so it may store up to the heaviest one using an union

View File

@ -313,8 +313,8 @@ struct se_abort_info {
*
* <kip> is the known input payload length. It is set by the stream endpoint
* that produce data and decremented once consumed by the app
* loyer. Depending on the enpoint, this value may be unset. It may be set
* only once if the payload lenght is fully known from the begining (a
* layer. Depending on the endpoint, this value may be unset. It may be set
* only once if the payload length is fully known from the beginning (a
* HTTP message with a content-length for instance), or incremented
* periodically when more data are expected (a chunk-encoded HTTP message
* for instance). On the app side, this value is decremented when data are

View File

@ -206,7 +206,7 @@ struct stktable {
void *ptr; /* generic ptr to check if set or not */
} write_to; /* updates received on the source table will also update write_to */
THREAD_ALIGN(64);
THREAD_ALIGN();
struct {
struct eb_root keys; /* head of sticky session tree */
@ -216,12 +216,12 @@ struct stktable {
__decl_thread(HA_RWLOCK_T sh_lock); /* for the trees above */
int next_exp; /* Next expiration for this table */
} shards[CONFIG_HAP_TBL_BUCKETS];
} buckets[CONFIG_HAP_TBL_BUCKETS];
unsigned int refcnt; /* number of local peer over all peers sections
attached to this table */
unsigned int current; /* number of sticky sessions currently in table */
THREAD_ALIGN(64);
THREAD_ALIGN();
struct eb_root updates; /* head of sticky updates sequence tree, uses updt_lock */
struct mt_list *pend_updts; /* list of updates to be added to the update sequence tree, one per thread-group */
@ -229,7 +229,7 @@ struct stktable {
unsigned int localupdate; /* uses updt_lock */
struct tasklet *updt_task;/* tasklet responsible for pushing the pending updates into the tree */
THREAD_ALIGN(64);
THREAD_ALIGN();
/* this lock is heavily used and must be on its own cache line */
__decl_thread(HA_RWLOCK_T updt_lock); /* lock protecting the updates part */

View File

@ -193,11 +193,11 @@ static inline void *stktable_data_ptr_idx(struct stktable *t, struct stksess *ts
return __stktable_data_ptr(t, ts, type) + idx*stktable_type_size(stktable_data_types[type].std_type);
}
/* return a shard number for key <key> of len <len> present in table <t>, for
/* return a bucket number for key <key> of len <len> present in table <t>, for
* use with the tree indexing. The value will be from 0 to
* CONFIG_HAP_TBL_BUCKETS-1.
*/
static inline uint stktable_calc_shard_num(const struct stktable *t, const void *key, size_t len)
static inline uint stktable_calc_bucket_num(const struct stktable *t, const void *key, size_t len)
{
#if CONFIG_HAP_TBL_BUCKETS > 1
return XXH32(key, len, t->hash_seed) % CONFIG_HAP_TBL_BUCKETS;
@ -219,13 +219,13 @@ static inline int __stksess_kill_if_expired(struct stktable *t, struct stksess *
* Decrease the refcount of a stksess and release it if the refcount falls to 0
* _AND_ if the session expired. Note,, the refcount is always decremented.
*
* This function locks the corresponding table shard to proceed. When this
* This function locks the corresponding table bucket to proceed. When this
* function is called, the caller must be sure it owns a reference on the
* stksess (refcount >= 1).
*/
static inline void stksess_kill_if_expired(struct stktable *t, struct stksess *ts)
{
uint shard;
uint bucket;
size_t len;
if (t->expire != TICK_ETERNITY && tick_is_expired(ts->expire, now_ms)) {
@ -234,15 +234,15 @@ static inline void stksess_kill_if_expired(struct stktable *t, struct stksess *t
else
len = t->key_size;
shard = stktable_calc_shard_num(t, ts->key.key, len);
bucket = stktable_calc_bucket_num(t, ts->key.key, len);
/* make the compiler happy when shard is not used without threads */
ALREADY_CHECKED(shard);
/* make the compiler happy when bucket is not used without threads */
ALREADY_CHECKED(bucket);
HA_RWLOCK_WRLOCK(STK_TABLE_LOCK, &t->shards[shard].sh_lock);
HA_RWLOCK_WRLOCK(STK_TABLE_LOCK, &t->buckets[bucket].sh_lock);
if (!HA_ATOMIC_SUB_FETCH(&ts->ref_cnt, 1))
__stksess_kill_if_expired(t, ts);
HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &t->shards[shard].sh_lock);
HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &t->buckets[bucket].sh_lock);
}
else
HA_ATOMIC_SUB_FETCH(&ts->ref_cnt, 1);

View File

@ -1,7 +1,7 @@
#ifndef _HAPROXY_STRESS_H
#define _HAPROXY_STRESS_H
#ifdef DEBUG_STRESS
#if defined(DEBUG_STRESS) && (DEBUG_STRESS > 0)
enum { mode_stress = 1 };
#else
enum { mode_stress = 0 };

View File

@ -91,7 +91,7 @@ extern struct pool_head *pool_head_task;
extern struct pool_head *pool_head_tasklet;
extern struct pool_head *pool_head_notification;
__decl_thread(extern HA_RWLOCK_T wq_lock THREAD_ALIGNED(64));
__decl_thread(extern HA_RWLOCK_T wq_lock THREAD_ALIGNED());
void __tasklet_wakeup_on(struct tasklet *tl, int thr);
struct list *__tasklet_wakeup_after(struct list *head, struct tasklet *tl);

View File

@ -51,7 +51,7 @@
/* declare a self-initializing spinlock, aligned on a cache line */
#define __decl_aligned_spinlock(lock) \
HA_SPINLOCK_T (lock) __attribute__((aligned(64))) = 0;
HA_SPINLOCK_T (lock) ALIGNED(64) = 0;
/* declare a self-initializing rwlock */
#define __decl_rwlock(lock) \
@ -59,7 +59,7 @@
/* declare a self-initializing rwlock, aligned on a cache line */
#define __decl_aligned_rwlock(lock) \
HA_RWLOCK_T (lock) __attribute__((aligned(64))) = 0;
HA_RWLOCK_T (lock) ALIGNED(64) = 0;
#else /* !USE_THREAD */
@ -72,7 +72,7 @@
/* declare a self-initializing spinlock, aligned on a cache line */
#define __decl_aligned_spinlock(lock) \
HA_SPINLOCK_T (lock) __attribute__((aligned(64))); \
HA_SPINLOCK_T (lock) THREAD_ALIGNED(); \
INITCALL1(STG_LOCK, ha_spin_init, &(lock))
/* declare a self-initializing rwlock */
@ -82,7 +82,7 @@
/* declare a self-initializing rwlock, aligned on a cache line */
#define __decl_aligned_rwlock(lock) \
HA_RWLOCK_T (lock) __attribute__((aligned(64))); \
HA_RWLOCK_T (lock) THREAD_ALIGNED(); \
INITCALL1(STG_LOCK, ha_rwlock_init, &(lock))
#endif /* USE_THREAD */

View File

@ -60,7 +60,6 @@ extern int thread_cpus_enabled_at_boot;
/* Only way found to replace variables with constants that are optimized away
* at build time.
*/
enum { all_tgroups_mask = 1UL };
enum { tid_bit = 1UL };
enum { tid = 0 };
enum { tgid = 1 };
@ -208,7 +207,6 @@ void wait_for_threads_completion();
void set_thread_cpu_affinity();
unsigned long long ha_get_pthread_id(unsigned int thr);
extern volatile unsigned long all_tgroups_mask;
extern volatile unsigned int rdv_requests;
extern volatile unsigned int isolated_thread;
extern THREAD_LOCAL unsigned int tid; /* The thread id */

View File

@ -42,7 +42,7 @@ struct thread_set {
ulong abs[(MAX_THREADS + LONGBITS - 1) / LONGBITS];
ulong rel[MAX_TGROUPS];
};
ulong grps; /* bit field of all non-empty groups, 0 for abs */
ulong nbgrps; /* Number of thread groups, 0 for abs */
};
/* tasklet classes */
@ -86,7 +86,7 @@ struct tgroup_info {
/* pad to cache line (64B) */
char __pad[0]; /* unused except to check remaining room */
char __end[0] __attribute__((aligned(64)));
char __end[0] THREAD_ALIGNED();
};
/* This structure describes the group-specific context (e.g. active threads
@ -103,7 +103,7 @@ struct tgroup_ctx {
/* pad to cache line (64B) */
char __pad[0]; /* unused except to check remaining room */
char __end[0] __attribute__((aligned(64)));
char __end[0] THREAD_ALIGNED();
};
/* This structure describes all the per-thread info we need. When threads are
@ -124,7 +124,7 @@ struct thread_info {
/* pad to cache line (64B) */
char __pad[0]; /* unused except to check remaining room */
char __end[0] __attribute__((aligned(64)));
char __end[0] THREAD_ALIGNED();
};
/* This structure describes all the per-thread context we need. This is
@ -150,7 +150,8 @@ struct thread_ctx {
struct list buffer_wq[DYNBUF_NBQ]; /* buffer waiters, 4 criticality-based queues */
struct list pool_lru_head; /* oldest objects in thread-local pool caches */
struct list streams; /* list of streams attached to this thread */
struct list quic_conns; /* list of active quic-conns attached to this thread */
struct list quic_conns_fe; /* list of active FE quic-conns attached to this thread */
struct list quic_conns_be; /* list of active BE quic-conns attached to this thread */
struct list quic_conns_clo; /* list of closing quic-conns attached to this thread */
struct list queued_checks; /* checks waiting for a connection slot */
struct list tasklets[TL_CLASSES]; /* tasklets (and/or tasks) to run, by class */

View File

@ -77,7 +77,7 @@ static inline int thread_set_nth_group(const struct thread_set *ts, int n)
{
int i;
if (ts->grps) {
if (ts->nbgrps) {
for (i = 0; i < MAX_TGROUPS; i++)
if (ts->rel[i] && !n--)
return i + 1;
@ -95,7 +95,7 @@ static inline ulong thread_set_nth_tmask(const struct thread_set *ts, int n)
{
int i;
if (ts->grps) {
if (ts->nbgrps) {
for (i = 0; i < MAX_TGROUPS; i++)
if (ts->rel[i] && !n--)
return ts->rel[i];
@ -111,7 +111,7 @@ static inline void thread_set_pin_grp1(struct thread_set *ts, ulong mask)
{
int i;
ts->grps = 1;
ts->nbgrps = 1;
ts->rel[0] = mask;
for (i = 1; i < MAX_TGROUPS; i++)
ts->rel[i] = 0;

View File

@ -47,23 +47,6 @@
/* return the largest possible integer of type <ret>, with all bits set */
#define MAX_RANGE(ret) (~(typeof(ret))0)
/* DEFVAL() returns either the second argument as-is, or <def> if absent. This
* is for use in macros arguments.
*/
#define DEFVAL(_def,...) _FIRST_ARG(NULL, ##__VA_ARGS__, (_def))
/* DEFNULL() returns either the argument as-is, or NULL if absent. This is for
* use in macros arguments.
*/
#define DEFNULL(...) DEFVAL(NULL, ##__VA_ARGS__)
/* DEFZERO() returns either the argument as-is, or 0 if absent. This is for
* use in macros arguments.
*/
#define DEFZERO(...) DEFVAL(0, ##__VA_ARGS__)
#define _FIRST_ARG(a, b, ...) b
/* options flags for parse_line() */
#define PARSE_OPT_SHARP 0x00000001 // '#' ends the line
#define PARSE_OPT_BKSLASH 0x00000002 // '\' escapes chars

View File

@ -1413,7 +1413,8 @@ static inline int warn_if_lower(const char *text, long min)
value = atol(text);
return value && value < min;
}
/* compare the current AWS-LC API number to a string */
int awslc_compare_current_api(const char *version);
/* compare the current OpenSSL version to a string */
int openssl_compare_current_version(const char *version);
/* compare the current OpenSSL name to a string */
@ -1489,4 +1490,6 @@ int path_base(const char *path, const char *base, char *dst, char **err);
void ha_freearray(char ***array);
void ha_memset_s(void *s, int c, size_t n);
#endif /* _HAPROXY_TOOLS_H */

View File

@ -33,7 +33,7 @@
#ifdef CONFIG_PRODUCT_BRANCH
#define PRODUCT_BRANCH CONFIG_PRODUCT_BRANCH
#else
#define PRODUCT_BRANCH "3.3"
#define PRODUCT_BRANCH "3.4"
#endif
#ifdef CONFIG_PRODUCT_STATUS

View File

@ -63,7 +63,7 @@
* the same split bit as its parent node, it is necessary its associated leaf
*
* When descending along the tree, it is possible to know that a search key is
* not present, because its XOR with both of the branches is stricly higher
* not present, because its XOR with both of the branches is strictly higher
* than the inter-branch XOR. The reason is simple : the inter-branch XOR will
* have its highest bit set indicating the split bit. Since it's the bit that
* differs between the two branches, the key cannot have it both set and

1
reg-tests/checks/certs Symbolic link
View File

@ -0,0 +1 @@
../ssl/certs/

View File

@ -1 +0,0 @@
../ssl/common.pem

View File

@ -39,7 +39,7 @@ haproxy htst -conf {
timeout connect "${HAPROXY_TEST_TIMEOUT-5s}"
frontend fe1
bind "fd@${fe1}" ssl crt ${testdir}/common.pem
bind "fd@${fe1}" ssl crt ${testdir}/certs/common.pem
frontend fe2
bind "fd@${fe2}"

View File

@ -45,10 +45,10 @@ haproxy htst -conf {
server fe1 ${htst_fe1_addr}:${htst_fe1_port}
frontend fe1
bind "fd@${fe1}" ssl crt ${testdir}/common.pem curves P-256:P-384
bind "fd@${fe1}" ssl crt ${testdir}/certs/common.pem curves P-256:P-384
frontend fe3
bind "fd@${fe3}" ssl crt ${testdir}/common.pem
bind "fd@${fe3}" ssl crt ${testdir}/certs/common.pem
} -start
haproxy h1 -conf {

View File

@ -62,7 +62,7 @@ haproxy htst -conf {
server fe1 ${htst_fe1_addr}:${htst_fe1_port}
frontend fe1
bind "fd@${fe1}" ssl crt ${testdir}/common.pem
bind "fd@${fe1}" ssl crt ${testdir}/certs/common.pem
} -start

View File

@ -60,15 +60,15 @@ haproxy h1 -conf {
frontend fe1
option httplog
log ${S1_addr}:${S1_port} len 2048 local0 debug err
bind "fd@${fe1}" ssl crt ${testdir}/common.pem
bind "fd@${fe1}" ssl crt ${testdir}/certs/common.pem
use_backend be1
frontend fe2
bind "fd@${fe2}" ssl crt ${testdir}/common.pem
bind "fd@${fe2}" ssl crt ${testdir}/certs/common.pem
use_backend be2
frontend fe3
bind "fd@${fe3}" ssl crt ${testdir}/common.pem
bind "fd@${fe3}" ssl crt ${testdir}/certs/common.pem
use_backend be3
} -start
@ -108,19 +108,19 @@ haproxy h2 -conf {
option httpchk OPTIONS * HTTP/1.1
http-check send hdr Host www
log ${S2_addr}:${S2_port} daemon
server srv1 ${h1_fe1_addr}:${h1_fe1_port} ssl crt ${testdir}/common.pem verify none check
server srv1 ${h1_fe1_addr}:${h1_fe1_port} ssl crt ${testdir}/certs/common.pem verify none check
backend be4
option log-health-checks
log ${S4_addr}:${S4_port} daemon
server srv2 ${h1_fe2_addr}:${h1_fe2_port} ssl crt ${testdir}/common.pem verify none check-ssl check
server srv2 ${h1_fe2_addr}:${h1_fe2_port} ssl crt ${testdir}/certs/common.pem verify none check-ssl check
backend be6
option log-health-checks
option httpchk OPTIONS * HTTP/1.1
http-check send hdr Host www
log ${S6_addr}:${S6_port} daemon
server srv3 127.0.0.1:80 crt ${testdir}/common.pem verify none check check-ssl port ${h1_fe3_port} addr ${h1_fe3_addr}:80
server srv3 127.0.0.1:80 crt ${testdir}/certs/common.pem verify none check check-ssl port ${h1_fe3_port} addr ${h1_fe3_addr}:80
} -start
syslog S1 -wait

1
reg-tests/compression/certs Symbolic link
View File

@ -0,0 +1 @@
../ssl/certs/

View File

@ -1 +0,0 @@
../ssl/common.pem

View File

@ -22,7 +22,7 @@ defaults
mode http
frontend main-https
bind "fd@${fe1}" ssl crt ${testdir}/common.pem
bind "fd@${fe1}" ssl crt ${testdir}/certs/common.pem
compression algo gzip
compression type text/html text/plain application/json application/javascript
compression offload

View File

@ -1 +0,0 @@
../ssl/ca-auth.crt

1
reg-tests/connection/certs Symbolic link
View File

@ -0,0 +1 @@
../ssl/certs/

View File

@ -1 +0,0 @@
../ssl/client1.pem

View File

@ -1 +0,0 @@
../ssl/common.pem

View File

@ -47,7 +47,7 @@ haproxy h1 -conf {
listen receiver
bind "fd@${feR}"
bind "fd@${feR_ssl}" ssl crt ${testdir}/common.pem
bind "fd@${feR_ssl}" ssl crt ${testdir}/certs/common.pem
bind "fd@${feR_proxy}" accept-proxy
http-request return status 200
http-after-response set-header http_first_request %[http_first_req]

View File

@ -24,7 +24,7 @@ haproxy h1 -conf {
server example ${h1_feR_addr}:${h1_feR_port} send-proxy-v2 proxy-v2-options unique-id ssl alpn XXX verify none
listen receiver
bind "fd@${feR}" ssl crt ${testdir}/common.pem accept-proxy
bind "fd@${feR}" ssl crt ${testdir}/certs/common.pem accept-proxy
http-request set-var(txn.proxy_unique_id) fc_pp_unique_id
http-after-response set-header proxy_unique_id %[var(txn.proxy_unique_id)]

View File

@ -29,7 +29,7 @@ backend be-reverse
server dev rhttp@ ssl sni hdr(x-name) verify none
frontend priv
bind "fd@${priv}" ssl crt ${testdir}/common.pem verify required ca-verify-file ${testdir}/ca-auth.crt alpn h2
bind "fd@${priv}" ssl crt ${testdir}/certs/common.pem verify required ca-verify-file ${testdir}/certs/ca-auth.crt alpn h2
tcp-request session attach-srv be-reverse/dev name ssl_c_s_dn(CN)
} -start
@ -45,7 +45,7 @@ defaults
listen li
bind "fd@${li}"
server h_edge "${h_edge_priv_addr}:${h_edge_priv_port}" ssl crt ${testdir}/client1.pem verify none alpn h2
server h_edge "${h_edge_priv_addr}:${h_edge_priv_port}" ssl crt ${testdir}/certs/client1.pem verify none alpn h2
} -start
# Run a client through private endpoint

Some files were not shown because too many files have changed in this diff Show More