Commit graph

12995 commits

Author SHA1 Message Date
Willy Tarreau
f70fdde591 BUILD: pools: fix build error on DEBUG_POOL_TRACING
When squashing commit add43fa43 ("DEBUG: pools: add new build option
DEBUG_POOL_TRACING") I managed to break the build and to fail to detect
it even after the rebase and a full rebuild :-(
2022-01-25 15:59:18 +01:00
Willy Tarreau
410942b92a BUILD: debug/cli: condition test of O_ASYNC to its existence
David Carlier reported a build breakage on Haiku since commit
5be7c198e ("DEBUG: cli: add a new "debug dev fd" expert command")
due to O_ASYNC not being defined. Ilya also reported it broke the
build on Cygwin. It's not that portable and sometimes defined as
O_NONBLOCK for portability. But here we don't even need that, as
we already condition other flags, let's just ignore it if it does
not exist.
2022-01-25 14:51:53 +01:00
Willy Tarreau
3a6af1e5e8 MINOR: fd: register the write side of the poller pipe as well
The poller's pipe was only registered on the read side since we don't
need to poll to write on it. But this leaves some known FDs so it's
better to also register the write side with no event. This will allow
to show them in "show fd" and to avoid dumping them as unhandled FDs.

Note that the only other type of unhandled FDs left are:
  - stdin/stdout/stderr
  - epoll FDs

The later can be registered upon startup though but at least a dummy
handler would be needed to keep the fdtab clean.
2022-01-24 20:41:25 +01:00
Willy Tarreau
5be7c198e5 DEBUG: cli: add a new "debug dev fd" expert command
This command will scan the whole file descriptors space to look for
existing FDs that are unknown to haproxy's fdtab, and will try to dump
a maximum number of information about them (including type, mode, device,
size, uid/gid, cloexec, O_* flags, socket types and addresses when
relevant). The goal is to help detecting inherited FDs from parent
processes as well as potential leaks.

Some of those listed are actually known but handled so deep into some
systems that they're not in the fdtab (such as epoll FDs or inter-
thread pipes). This might be refined in the future so that these ones
become known and do not appear.

Example of output:

 $ socat - /tmp/sock1 <<< "expert-mode on;debug dev fd"

    0 type=tty. mod=0620 dev=0x8803 siz=0 uid=1000 gid=5 fs=0x16 ino=0x6 getfd=+0 getfl=O_RDONLY,O_APPEND
    1 type=tty. mod=0620 dev=0x8803 siz=0 uid=1000 gid=5 fs=0x16 ino=0x6 getfd=+0 getfl=O_RDONLY,O_APPEND
    2 type=tty. mod=0620 dev=0x8803 siz=0 uid=1000 gid=5 fs=0x16 ino=0x6 getfd=+0 getfl=O_RDONLY,O_APPEND
    3 type=pipe mod=0600 dev=0 siz=0 uid=1000 gid=100 fs=0xc ino=0x18112348 getfd=+0
    4 type=epol mod=0600 dev=0 siz=0 uid=0 gid=0 fs=0xd ino=0x3674 getfd=+0 getfl=O_RDONLY
   33 type=pipe mod=0600 dev=0 siz=0 uid=1000 gid=100 fs=0xc ino=0x24af8251 getfd=+0 getfl=O_RDONLY
   34 type=epol mod=0600 dev=0 siz=0 uid=0 gid=0 fs=0xd ino=0x3674 getfd=+0 getfl=O_RDONLY
   36 type=pipe mod=0600 dev=0 siz=0 uid=1000 gid=100 fs=0xc ino=0x24af8d1b getfd=+0 getfl=O_RDONLY
   37 type=epol mod=0600 dev=0 siz=0 uid=0 gid=0 fs=0xd ino=0x3674 getfd=+0 getfl=O_RDONLY
   39 type=pipe mod=0600 dev=0 siz=0 uid=1000 gid=100 fs=0xc ino=0x24afa04f getfd=+0 getfl=O_RDONLY
   41 type=pipe mod=0600 dev=0 siz=0 uid=1000 gid=100 fs=0xc ino=0x24af8252 getfd=+0 getfl=O_RDONLY
   42 type=epol mod=0600 dev=0 siz=0 uid=0 gid=0 fs=0xd ino=0x3674 getfd=+0 getfl=O_RDONLY
2022-01-24 20:26:09 +01:00
Willy Tarreau
add43fa43e DEBUG: pools: add new build option DEBUG_POOL_TRACING
This new option, when set, will cause the callers of pool_alloc() and
pool_free() to be recorded into an extra area in the pool that is expected
to be helpful for later inspection (e.g. in core dumps). For example it
may help figure that an object was released to a pool with some sub-fields
not yet released or that a use-after-free happened after releasing it,
with an immediate indication about the exact line of code that released
it (possibly an error path).

This only works with the per-thread cache, and even objects refilled from
the shared pool directly into the thread-local cache will have a NULL
there. That's not an issue since these objects have not yet been freed.
It's worth noting that pool_alloc_nocache() continues not to set any
caller pointer (e.g. when the cache is empty) because that would require
a possibly undesirable API change.

The extra cost is minimal (one pointer per object) and this completes
well with DEBUG_POOL_INTEGRITY.
2022-01-24 16:40:48 +01:00
Willy Tarreau
0e2a5b4b61 MINOR: pools: extend pool_cache API to pass a pointer to a caller
This adds a caller to pool_put_to_cache() and pool_get_from_cache()
which will optionally be used to pass a pointer to their callers. For
now it's not used, only the API is extended to support this pointer.
2022-01-24 16:40:48 +01:00
Willy Tarreau
d392973dcc MINOR: pools: partially uninline pool_alloc()
The pool_alloc() function was already a wrapper to __pool_alloc() which
was also inlined but took a set of flags. This latter was uninlined and
moved to pool.c, and pool_alloc()/pool_zalloc() turned to macros so that
they can more easily evolve to support debugging options.

The number of call places made this code grow over time and doing only
this change saved ~1% of the whole executable's size.
2022-01-24 16:40:48 +01:00
Willy Tarreau
15c322c413 MINOR: pools: partially uninline pool_free()
The pool_free() function has become a bit big over time due to the
extra consistency checks. It used to remain inline only to deal
cleanly with the NULL pointer free that's quite present on some
structures (e.g. in stream_free()).

Here we're splitting the function in two:
  - __pool_free() does the inner block without the pointer test and
    becomes a function ;

  - pool_free() is now a macro that only checks the pointer and calls
    __pool_free() if needed.

The use of a macro versus an inline function is only motivated by an
easier intrumentation of the code later.

With this change, the code size reduces by ~1%, which means that at
this point all pool_free() call places used to represent more than
1% of the total code size.
2022-01-24 16:40:48 +01:00
Amaury Denoyelle
7c564bfdd3 MINOR: ssl: fix build in release mode
Fix potential null pointer dereference. In fact, this case is not
possible, only a mistake in SSL ex-data initialization may cause it :
either connection is set or quic_conn, which allows to retrieve
the bind_conf.

A BUG_ON was already present but this does not cover release build.
2022-01-24 11:15:48 +01:00
Amaury Denoyelle
33ac346ba8 MINOR: quic: initialize ssl_sock_ctx alongside the quic_conn
Extract the allocation of ssl_sock_ctx from qc_conn_init to a dedicated
function qc_conn_alloc_ssl_ctx. This function is called just after
allocating a new quic_conn, without waiting for the initialization of
the connection. It allocates the ssl_sock_ctx and the quic_conn tasklet.

This change is now possible because the SSL callbacks are dealing with a
quic_conn instance.

This change is required to be able to delay the connection allocation
and handle handshake packets without it.
2022-01-24 10:30:49 +01:00
Amaury Denoyelle
9320dd5385 MEDIUM: quic/ssl: add new ex data for quic_conn
Allow to register quic_conn as ex-data in SSL callbacks. A new index is
used to identify it as ssl_qc_app_data_index.

Replace connection by quic_conn as SSL ex-data when initializing the QUIC
SSL session. When using SSL callbacks in QUIC context, the connection is
now NULL. Used quic_conn instead to retrieve the required parameters.
Also clean up

The same changes are conducted inside the QUIC SSL methods of xprt-quic
: connection instance usage is replaced by quic_conn.
2022-01-24 10:30:49 +01:00
Amaury Denoyelle
57af069571 MINOR: quic: set listener accept cb on parsing
Define a special accept cb for QUIC listeners to quic_session_accept().
This operation is conducted during the proto.add callback when creating
listeners.

A special care is now taken care when setting the standard callback
session_accept_fd() to not overwrite if already defined by the proto
layer.
2022-01-24 10:30:49 +01:00
Amaury Denoyelle
29632b8b10 MINOR: quic: remove dereferencement of connection when possible
Some functions of xprt-quic were still using connection instead of
quic_conn. This must be removed as the two are decorrelated : a
quic_conn can exist without a connection.
2022-01-24 10:30:49 +01:00
Amaury Denoyelle
74f2292557 MINOR: quic: fix indentation in qc_send_ppkts
Adjust wrong mixing of tabs/spaces.
2022-01-24 10:30:49 +01:00
Amaury Denoyelle
4d29504c58 MINOR: quic: add missing include in quic_sock
Add quic_sock.h include in corresponding source file quic_sock.c.
2022-01-24 10:30:49 +01:00
Willy Tarreau
0575d8fd76 DEBUG: pools: add new build option DEBUG_POOL_INTEGRITY
When enabled, objects picked from the cache are checked for corruption
by comparing their contents against a pattern that was placed when they
were inserted into the cache. Objects are also allocated in the reverse
order, from the oldest one to the most recent, so as to maximize the
ability to detect such a corruption. The goal is to detect writes after
free (or possibly hardware memory corruptions). Contrary to DEBUG_UAF
this cannot detect reads after free, but may possibly detect later
corruptions and will not consume extra memory. The CPU usage will
increase a bit due to the cost of filling/checking the area and for the
preference for cold cache instead of hot cache, though not as much as
with DEBUG_UAF. This option is meant to be usable in production.
2022-01-21 19:07:48 +01:00
Frédéric Lécaille
39ba1c3e12 MINOR: quic: Wrong packet number space selection
It is possible that the listener is in INITIAL state, but have to probe
with Handshake packets. In this case, when entering qc_prep_pkts() there
is nothing to do. We must select the next packet number space (or encryption
level) to be able to probe with such packet type.
2022-01-21 17:38:11 +01:00
Frédéric Lécaille
2cca241780 MINOR: quic: Add QUIC_FT_RETIRE_CONNECTION_ID parsing case
At this time, we do not do anything. This is only to prevent a packet
from being parsed and to pass some test irrespective of the CIDs management.
2022-01-21 17:38:11 +01:00
Amaury Denoyelle
2d9794b03a MINOR: quic: free SSL context on quic_conn free
Free the SSL context attached to the quic_conn when freeing the
connection. This fixes a memory leak for every QUIC connection.
2022-01-21 15:20:07 +01:00
Amaury Denoyelle
760da3be57 MINOR: quic: fix race-condition on xprt tasklet free
Remove the unsafe call to tasklet_free in quic_close. At this stage the
tasklet may already be scheduled by an other threads even after if the
quic_conn refcount is now null. It will probably cause a crash on the
next tasklet processing.

Use tasklet_kill instead to ensure that the tasklet is freed in a
thread-safe way. Note that quic_conn_io_cb is not protected by the
refcount so only the quic_conn pinned thread must kill the tasklet.
2022-01-21 15:19:31 +01:00
Amaury Denoyelle
2eb7b30715 MINOR: quic: adjust quic_conn refcount decrement
Adjust slightly refcount code decrement on quic_conn close. A new
function named quic_conn_release is implemented. This function is
responsible to remove the quic_conn from CIDs trees and decrement the
refcount to free the quic_conn once all threads have finished to work
with it.

For now, quic_close is responsible to call it so the quic_conn is
scheduled to be free by upper layers. In the future, it may be useful to
delay it to be able to send remaining data or waiting for missing ACKs
for example.

This simplify quic_conn_drop which do not require the lock anymore.
Also, this can help to free the connection more quickly in some cases.
2022-01-21 15:03:17 +01:00
Amaury Denoyelle
9c4da93796 MINOR: quic: do not use quic_conn after dropping it
quic_conn_drop decrement the refcount and may free the quic_conn if
reaching 0. The quic_conn should not be dereferenced again after it in
any case even for traces.
2022-01-21 15:02:56 +01:00
Willy Tarreau
6c539c4b8c BUG/MINOR: stream: make the call_rate only count the no-progress calls
We have an anti-looping protection in process_stream() that detects bugs
that used to affect a few filters like compression in the past which
sometimes forgot to handle a read0 or a particular error, leaving a
thread looping at 100% CPU forever. When such a condition is detected,
an alert it emitted and the process is killed so that it can be replaced
by a sane one:

  [ALERT]    (19061) : A bogus STREAM [0x274abe0] is spinning at 2057156
             calls per second and refuses to die, aborting now! Please
             report this error to developers [strm=0x274abe0,3 src=unix
             fe=MASTER be=MASTER dst=<MCLI> txn=(nil),0 txn.req=-,0
             txn.rsp=-,0 rqf=c02000 rqa=10000 rpf=88000021 rpa=8000000
             sif=EST,40008 sib=DIS,84018 af=(nil),0 csf=0x274ab90,8600
             ab=0x272fd40,1 csb=(nil),0
             cof=0x25d5d80,1300:PASS(0x274aaf0)/RAW((nil))/unix_stream(9)
             cob=(nil),0:NONE((nil))/NONE((nil))/NONE(0) filters={}]
    call trace(11):
    |       0x4dbaab [c7 04 25 01 00 00 00 00]: stream_dump_and_crash+0x17b/0x1b4
    |       0x4df31f [e9 bd c8 ff ff 49 83 7c]: process_stream+0x382f/0x53a3
    (...)

One problem with this detection is that it used to only count the call
rate because we weren't sure how to make it more accurate, but the
threshold was high enough to prevent accidental false positives.

There is actually one case that manages to trigger it, which is when
sending huge amounts of requests pipelined on the master CLI. Some
short requests such as "show version" are sufficient to be handled
extremely fast and to cause a wake up of an analyser to parse the
next request, then an applet to handle it, back and forth. But this
condition is not an error, since some data are being forwarded by
the stream, and it's easy to detect it.

This patch modifies the detection so that update_freq_ctr() only
applies to calls made without CF_READ_PARTIAL nor CF_WRITE_PARTIAL
set on any of the channels, which really indicates that nothing is
happening at all.

This is greatly sufficient and extremely effective, as the call above
is still caught (shutr being ignored by an analyser) while a loop on
the master CLI now has no effect. The "call_rate" field in the detailed
"show sess" output will now be much lower, except for bogus streams,
which may help spot them. This field is only there for developers
anyway so it's pretty fine to slightly adjust its meaning.

This patch could be backported to stable versions in case of reports
of such an issue, but as that's unlikely, it's not really needed.
2022-01-20 18:56:57 +01:00
Willy Tarreau
a4e4d66f70 BUG/MEDIUM: mcli: always realign wrapping buffers before parsing them
Pipelined commands easily result in request buffers to wrap, and the
master-cli parser only deals with linear buffers since it needs contiguous
keywords to look for in a list. As soon as a buffer wraps, some commands
are ignored and the parser is called in loops because the wrapped data
do not leave the buffer.

Let's take the easiest path that's already used at the HTTP layer, we
simply realign the buffer if its input wraps. This rarely happens anyway
(typically once per buffer), remains reasonably cheap and guarantees this
cannot happen anymore.

This needs to be backported as far as 2.0.
2022-01-20 18:56:57 +01:00
Willy Tarreau
6cd93f52e9 BUG/MEDIUM: mcli: do not try to parse empty buffers
When pcli_parse_request() is called with an empty buffer, it still tries
to parse it and can go on believing it finds an empty request if the last
char before the beginning of the buffer is a '\n'. In this case it overwrites
it with a zero and processes it as an empty command, doing nothing but not
making the buffer progress. This results in an infinite loop that is stopped
by the watchdog. For a reason related to another issue (yet to be fixed),
this can easily be reproduced by pipelining lots of commands such as
"show version".

Let's add a length check after the search for a '\n'.

This needs to be backported as far as 2.0.
2022-01-20 18:56:57 +01:00
Christopher Faulet
0f727dabf5 BUG/MEDIUM: cli: Never wait for more data on client shutdown
When a shutdown is detected on the cli, we try to execute all pending
commands first before closing the connection. It is required because
commands execution is serialized. However, when the last part is a partial
command, the cli connection is not closed, waiting for more data. Because
there is no timeout for now on the cli socket, the connection remains
infinitely in this state. And because the maxconn is set to 10, if it
happens several times, the cli socket quickly becomes unresponsive because
all its slots are waiting for more data on a closed connections.

This patch should fix the issue #1512. It must be backported as far as 2.0.
2022-01-20 18:56:39 +01:00
Frédéric Lécaille
94fca87f6a MINOR: quic: Probe even if coalescing
Again, we fix a reminiscence of the way we probed before probing by packet.
When we were probing by datagram we inspected <prv_pkt> to know if we were
coalescing several packets. There is no need to do that at all when probing by packet.
Furthermore this could lead to blocking situations where we want to probe but
are limited by the congestion control (<cwnd> path variable). This must not be
the case. When probing we must do it regardless of the congestion control.
2022-01-20 16:43:06 +01:00
Frédéric Lécaille
e87524d41c MINOR: quic: Release asap TX frames to be transmitted
This is done only for ack-eliciting frames to be sent from Initial and Handshake
packet number space when discarding them.
2022-01-20 16:43:06 +01:00
Frédéric Lécaille
a6255f53e8 MINOR: quic: Release RX Initial packets asap
This is to free up some space in the RX buffer as soon as possible.
2022-01-20 16:43:06 +01:00
Frédéric Lécaille
04e63aa6ef MINOR: quic: Speeding up handshake completion
If a client resend Initial CRYPTO data, this is because it did not receive all
the server Initial CRYPTO data. With this patch we prepare a fast retransmission
without waiting for the PTO timer expiration sending old Initial CRYPTO data,
coalescing them with Handshake CRYPTO if present in the same datagram. Furthermore
we send also a datagram made of previously sent Hanshashke CRYPTO data if any.
2022-01-20 16:43:06 +01:00
Frédéric Lécaille
f4e5a7c644 MINOR: quic: Probe regardless of the congestion control
When probing, we must not take into an account the congestion control window.
This was not completely correctly implemented: qc_build_frms() could fail
because of this limit when comparing the head of the packet againts the
congestion control window. With this patch we make it fail only when
we are not probing.
2022-01-20 16:43:06 +01:00
Frédéric Lécaille
0fa553d0c2 MINOR: quic: Send two ack-eliciting packets when probing packet number spaces
This is to avoid too much PTO timer expirations for 01RTT and Handshake packet
number spaces. Furthermore we are not limited by the anti-amplication for 01RTT
packet number space. According to the RFC we can send up to two packets.
2022-01-20 16:43:06 +01:00
Frédéric Lécaille
ce6602d887 CLEANUP: quic: Replace <nb_pto_dgrams> by <probe>
This modification should have come with this commit:
    "MINOR: quic: Remove nb_pto_dgrams quic_conn struct member"
where the nb_pto_dgrams quic_conn struct member was removed.
2022-01-20 16:43:06 +01:00
Frédéric Lécaille
8b6ea17105 MINOR: quic: Add the number of TX bytes to traces
This should be helpful to diagnose some issues regarding packet loss
and recovery issues.
2022-01-20 16:43:06 +01:00
Frédéric Lécaille
cba4cd427e MINOR: quic: Splice the frames which could not be added to packets
When building packets to send, we build frames computing their sizes
to have more chance to be added to new packets. There are rare cases
where this packet coult not be built because of the congestion control
which may for instance prevent us from building a packet with padding
(retransmitted Initial packets). In such a case, the pre-built frames
were lost because added to the packet frame list but not move packet
to the packet number space they come from.

With this patch we add the frames to the packet only if it could be built
and move them back to the packet number space if not.
2022-01-20 16:43:06 +01:00
Frédéric Lécaille
82468ea98e MINOR: quic: Remove the packet number space TX MT_LIST
There is no need to use an MT_LIST to store frames to send from a packet
number space. This is a reminiscence for multi-threading support for the TX part.
2022-01-20 16:43:06 +01:00
Frédéric Lécaille
7065dd0895 MINOR: quic: Retransmit the TX frames in the same order
This is only to please the peer. We resend the TX frames in the
same order they have been sent.
2022-01-20 16:35:43 +01:00
Willy Tarreau
39a0a1e120 MEDIUM: h2/hpack: emit a Dynamic Table Size Update after settings change
As reported by @jinsubsim in github issue #1498, there is an
interoperability issue between nghttp2 as a client and a few servers
among which haproxy (in fact likely all those which do not make use
of the dynamic headers table in responses or which do not intend to
use a larger table), when reducing the header table size below 4096.
These are easily testable this way:

  nghttp -v -H":method: HEAD" --header-table-size=0 https://$SITE

It will result in a compression error for those which do not start
with an HPACK dynamic table size update opcode.

There is a possible interpretation of the H2 and HPACK specs that
says that an HPACK encoder must send an HPACK headers table update
confirming the new size it will be using after having acknowledged
it, because since it's possible for a decoder to advertise a late
SETTINGS and change it after transfers have begun, the initially
advertised value might very well be seen as a first change from the
initial setting, and the HPACK spec doesn't specify the side which
causes the change that triggers a DTSU update, which was essentially
summed up in this question from nghttp2's author when this issue
was already raised 6 years ago, but which didn't really find a solid
response by then:

  https://lists.w3.org/Archives/Public/ietf-http-wg/2015OctDec/0107.html

The ongoing consensus based on what some servers are doing and that aims
at limiting interoperability issues seems to be that a DTSU is expected
for each reduction from the current size, which should be reflected in
the next revision of the H2 spec:

  https://github.com/httpwg/http2-spec/pull/1005

Given that we do not make use of this table we can emit a DTSU of zero
before encoding any HPACK frame. However, some clients do not support
receiving DTSU with such values (e.g. VTest) so we cannot do it
inconditionnally!

The current patch aims at sticking as close to the spec as possible by
proceeding this way:
  - when a SETTINGS_HEADER_TABLE_SIZE is received, a flag is set
    indicating that the value changed
  - before sending any HPACK frame, this flag is checked to see if
    an update is wanted and if none was sent
  - in this case a DTSU of size zero is emitted and a flag is set
    to mention it was emitted so that it never has to be sent again

This addresses the problem with nghttp2 without affecting VTest.

More context is available here:
  https://github.com/nghttp2/nghttp2/issues/1660
  https://lists.w3.org/Archives/Public/ietf-http-wg/2021OctDec/0235.html

Many thanks to @jinsubsim for this report and participating to the issue
that led to an improvement of the H2 spec.

This should be backported to stable releases in a timely manner, ideally
as far as 2.4 once the h2spec update is merged, then to other versions
after a few months of observation or in case an issue around this is
reported.
2022-01-20 05:01:03 +01:00
Willy Tarreau
0011c25144 BUG/MINOR: cli: avoid O(bufsize) parsing cost on pipelined commands
Sending pipelined commands on the CLI using a semi-colon as a delimiter
has a cost that grows linearly with the buffer size, because co_getline()
is called for each word and looks up a '\n' in the whole buffer while
copying its contents into a temporary buffer.

This causes huge parsing delays, for example 3s for 100k "show version"
versus 110ms if parsed only once for a default 16k buffer.

This patch makes use of the new co_getdelim() function to support both
an LF and a semi-colon as delimiters so that it's no more needed to parse
the whole buffer, and that commands are instantly retrieved. We still
need to rely on co_getline() in payload mode as escapes and semi-colons
are not used there.

It should likely be backported where CLI processing speed matters, but
will require to also backport previous patch "MINOR: channel: add new
function co_getdelim() to support multiple delimiters". It's worth noting
that backporting it without "MEDIUM: cli: yield between each pipelined
command" would significantly increase the ratio of disconnections caused
by empty request buffers, for the sole reason that the currently slow
parsing grants more time to request data to come in. As such it would
be better to backport the patch above before taking this one.
2022-01-19 19:16:47 +01:00
Willy Tarreau
c514365317 MINOR: channel: add new function co_getdelim() to support multiple delimiters
For now we have co_getline() which reads a buffer and stops on LF, and
co_getword() which reads a buffer and stops on one arbitrary delimiter.
But sometimes we'd need to stop on a set of delimiters (CR and LF, etc).

This patch adds a new function co_getdelim() which takes a set of delimiters
as a string, and constructs a small map (32 bytes) that's looked up during
parsing to stop after the first delimiter found within the set. It also
supports an optional escape character that skips a delimiter (typically a
backslash). For the rest it works exactly like the two other variants.
2022-01-19 19:16:47 +01:00
Willy Tarreau
fa7b4f6691 MEDIUM: cli: yield between each pipelined command
Pipelining commands on the CLI is sometimes needed for batched operations
such as map deletion etc, but it causes two problems:
  - some possibly long-running commands will be run in series without
    yielding, possibly causing extremely long latencies that will affect
    quality of service and even trigger the watchdog, as seen in github
    issue #1515.

  - short commands that end on a buffer size boundary, when not run in
    interactive mode, will often cause the socket to be closed when
    the last command is parsed, because the buffer is empty.

This patch proposes a small change to this: by yielding in the CLI applet
after processing a command when there are data left, we significantly
reduce the latency, since only one command is executed per call, and
we leave an opportunity for the I/O layers to refill the request buffer
with more commands, hence to execute all of them much more often.

With this change there's no more watchdog triggered on long series of
"del map" on large map files, and the operations are much less disturbed.
It would be desirable to backport this patch to stable versions after some
period of observation in recent versions.
2022-01-19 19:16:47 +01:00
William Dauchy
a087f87875 BUG/MEDIUM: server: avoid changing healthcheck ctx with set server ssl
While giving a fresh try to `set server ssl` (which I wrote), I realised
the behavior is a bit inconsistent. Indeed when using this command over
a server with ssl enabled for the data path but also for the health
check path we have:

- data and health check done using tls
- emit `set server be_foo/srv0 ssl off`
- data path and health check path becomes plain text
- emit `set server be_foo/srv0 ssl on`
- data path becomes tls and health check path remains plain text

while I thought the end result would be:
- data path and health check path comes back in tls

In the current code we indeed erase all connections while deactivating,
but restore only the data path while activating.  I made this mistake in
the past because I was testing with a case where the health check plain
text by default.

There are several ways to solve this issue. The cleanest one would
probably be to avoid changing the health check connection when we use
`set server ssl` command, and create a new command `set server
ssl-check` to change this. For now I assumed this would be ok to simply
avoid changing the health check path and be more consistent.

This patch tries to address that and also update the documentation. It
should not break the existing usage with health check on plain text, as
in this case they should have `no-check-ssl` in defaults.  Without this
patch, it makes the command unusable in an env where you have a list of
server to add along the way with initial `server-template`, and all
using tls for data and healthcheck path.

For 2.6 we should probably reconsider and add `set server ssl-check`
command for better granularity of cases.

If this solution is accepted, this patch should be backported up to >=
2.4.

The alternative solution was to restore the previous state, but I
believe this will create even more confusion in the future.

Signed-off-by: William Dauchy <wdauchy@gmail.com>
2022-01-18 12:05:17 +01:00
William Lallemand
01e2be84d7 BUG/MINOR: httpclient/lua: don't pop the lua stack when getting headers
hlua_httpclient_table_to_hdrs() does a lua_pop(L, 1) at the end of the
function, this is supposed to be done in the caller and it is already be
done in hlua_httpclient_send().

This call has the consequence of poping the next parameter of the
httpclient, ignoring it.

This patch fixes the issue by removing the lua_pop(L, 1).

Must be backported in 2.5.
2022-01-14 20:51:31 +01:00
William Lallemand
bad9c8cac4 BUG/MINOR: httpclient: set default Accept and User-Agent headers
Some servers require at least an Accept and a User-Agent header in the
request. This patch sets some default value.

Must be backported in 2.5.
2022-01-14 20:46:21 +01:00
William Lallemand
e1e045f4d7 BUG/MINOR: httpclient: don't send an empty body
Forbid the httpclient to send an empty chunked client when there is no
data to send. It does happen when doing a simple GET too.

Must be backported in 2.5.
2022-01-14 18:10:43 +01:00
Christopher Faulet
28e7ba8688 BUG/MEDIUM: htx: Adjust length to add DATA block in an empty HTX buffer
htx_add_data() is able to partially consume data. However there is a bug
when the HTX buffer is empty.  The data length is not properly
adjusted. Thus, if it exceeds the HTX buffer size, no block is added. To fix
the issue, the length is now adjusted first.

This patch must be backported as far as 2.0.
2022-01-13 09:34:22 +01:00
Frédéric Lécaille
b80b20c6ff MINOR: quic: Do not wakeup the I/O handler before the mux is started
If we wakeup the I/O handler before the mux is started, it is possible
it has enough time to parse the ClientHello TLS message and update the
mux transport parameters, leading to a crash.
So, we initialize ->qcc quic_conn struct member at the very last time,
when the mux if fully initialized. The condition to wakeup the I/O handler
from lstnr_rcv_pkt() is: xprt context and mux both initialized.
Note that if the xprt context is initialized, it implies its tasklet is
initialized. So, we do not check anymore this latter condition.
2022-01-12 18:08:29 +01:00
Frédéric Lécaille
bec186dde5 MINOR: quic: As server, skip 0-RTT packet number space
This is true only when we are building packets. A QUIC server never
sends 0-RTT packets. So let't skip the associated TLS encryption level.
2022-01-12 18:08:29 +01:00
Willy Tarreau
3b990fe0be BUG/MEDIUM: connection: properly leave stopping list on error
The stopping-list management introduced by commit d3a88c1c3 ("MEDIUM:
connection: close front idling connection on soft-stop") missed two
error paths in the H1 and H2 muxes. The effect is that if a stream
or HPACK table couldn't be allocated for these incoming connections,
we would leave with the connection freed still attached to the
stopping_list and it would never leave it, resulting in use-after-free
hence either a crash or a data corruption.

This is marked as medium as it only happens under extreme memory pressure
or when playing with tune.fail-alloc. Other stability issues remain in
such a case so that abnormal behaviors cannot be explained by this bug
alone.

This must be backported to 2.4.
2022-01-12 17:31:01 +01:00
Amaury Denoyelle
9ab2fb3921 MINOR: quic: free xprt tasklet on its thread
Free the ssl_sock_ctx tasklet in quic_close() instead of
quic_conn_drop(). This ensures that the tasklet is destroyed safely by
the same thread.

This has no impact as the free operation was previously conducted with
care and should not be responsible of any crash.
2022-01-12 15:21:27 +01:00
Amaury Denoyelle
b76ae69513 MEDIUM: quic: implement Retry emission
Implement the emission of Retry packets. These packets are emitted in
response to Initial from clients without token. The token from the Retry
packet contains the ODCID from the Initial packet.

By default, Retry packet emission is disabled and the handshake can
continue without address validation. To enable Retry, a new bind option
has been defined named "quic-force-retry". If set, the handshake must be
conducted only after receiving a token in the Initial packet.
2022-01-12 11:08:48 +01:00
Amaury Denoyelle
c3b6f4d484 MINOR: quic: define retry_source_connection_id TP
Define a new QUIC transport parameter retry_source_connection_id. This
parameter is set only by server, after issuing a Retry packet.
2022-01-12 11:08:48 +01:00
Amaury Denoyelle
5ff1c9778c MEDIUM: quic: implement Initial token parsing
Implement the parsing of token from Initial packets. It is expected that
the token contains a CID which is the DCID from the Initial packet
received from the client without token which triggers a Retry packet.
This CID is then used for transport parameters.

Note that at the moment Retry packet emission is not implemented. This
will be achieved in a following commit.
2022-01-12 11:08:48 +01:00
Amaury Denoyelle
6efec292ef MINOR: quic: implement Retry TLS AEAD tag generation
Implement a new QUIC TLS related function
quic_tls_generate_retry_integrity_tag(). This function can be used to
calculate the AEAD tag of a Retry packet.
2022-01-12 11:08:48 +01:00
Amaury Denoyelle
c8b4ce4a47 MINOR: quic: add config parse source file
Create a new dedicated source file for QUIC related options parsing on
the bind line.
2022-01-12 11:08:48 +01:00
Amaury Denoyelle
ce340fe4a7 MINOR: quic: fix return of quic_dgram_read
It is expected that quic_dgram_read() returns the total number of bytes
read. Fix the return value when the read has been successful. This bug
has no impact as in the end the return value is not checked by the
caller.
2022-01-12 11:08:48 +01:00
Frédéric Lécaille
1aa57d32bb MINOR: quic: Do not dereference ->conn quic_conn struct member
->conn quic_conn struct member is a connection struct object which may be
released from several places. With this patch we do our best to stop dereferencing
this member as much as we can.
2022-01-12 09:49:49 +01:00
Frédéric Lécaille
ba85acdc70 MINOR: quid: Add traces quic_close() and quic_conn_io_cb()
This is to have an idea of possible remaining issues regarding the
connection terminations.
2022-01-11 16:56:04 +01:00
Frédéric Lécaille
81cd3c8eed MINOR: quic: Wrong CRYPTO frame concatenation
This commit was not correct:
	 "MINOR: quic: Only one CRYPTO frame by encryption level"
Indeed, when receiving CRYPTO data from TLS stack for a packet number space,
there are rare cases where there is already other frames than CRYPTO data frames
in the packet number space, especially for 01RTT packet number space.  This is
very often with quant as client.
2022-01-11 16:12:31 +01:00
Frédéric Lécaille
2fe8b3be20 MINOR: quic: Flag the connection as being attached to a listener
We do not rely on connection objects to know if we are a listener or not.
2022-01-11 16:12:31 +01:00
Frédéric Lécaille
19cd46e6e5 MINOR: quic: Reset ->conn quic_conn struct member when calling qc_release()
There may be remaining locations where ->conn quic_conn struct member
is used. So let's reset this.
Add a trace to have an idead when this connection is released.
2022-01-11 16:12:31 +01:00
Frédéric Lécaille
5f7f118b31 MINOR: quic: Remaining TRACEs with connection as firt arg
This is a quic_conn struct which is expected by TRACE_()* macros
2022-01-11 16:12:31 +01:00
David CARLIER
bb10dad5a8 BUILD: cpuset: fix build issue on macos introduced by previous change
The build on macos was broken by recent commit df91cbd58 ("MINOR: cpuset:
switch to sched_setaffinity for FreeBSD 14 and above."), let's move the
variable declaration inside the ifdef.
2022-01-11 15:09:49 +01:00
Christopher Faulet
b4eca0e908 BUG/MAJOR: mux-h1: Don't decrement .curr_len for unsent data
A regression was introduced by commit 140f1a58 ("BUG/MEDIUM: mux-h1: Fix
splicing by properly detecting end of message"). To detect end of the
outgoing message, when the content-length is announced, we count amount of
data already sent. But only data really sent must be counted.

If the output buffer is full, we can fail to send data (fully or
partially). In this case, we must take care to only count sent
data. Otherwise we may think too much data were sent and an internal error
may be erroneously reported.

This patch should fix issues #1510 and #1511. It must be backported as far
as 2.4.
2022-01-11 09:15:13 +01:00
Remi Tricot-Le Breton
a996763619 BUG/MINOR: ssl: Store client SNI in SSL context in case of ClientHello error
If an error is raised during the ClientHello callback on the server side
(ssl_sock_switchctx_cbk), the servername callback won't be called and
the client's SNI will not be saved in the SSL context. But since we use
the SSL_get_servername function to return this SNI in the ssl_fc_sni
sample fetch, that means that in case of error, such as an SNI mismatch
with a frontend having the strict-sni option enabled, the sample fetch
would not work (making strict-sni related errors hard to debug).

This patch fixes that by storing the SNI as an ex_data in the SSL
context in case the ClientHello callback returns an error. This way the
sample fetch can fallback to getting the SNI this way. It will still
first call the SSL_get_servername function first since it is the proper
way of getting a client's SNI when the handshake succeeded.

In order to avoid memory allocations are runtime into this highly used
runtime function, a new memory pool was created to store those client
SNIs. Its entry size is set to 256 bytes since SNIs can't be longer than
255 characters.

This fixes GitHub #1484.

It can be backported in 2.5.
2022-01-10 16:31:22 +01:00
William Lallemand
f82afbb9cd BUG/MEDIUM: mworker: don't use _getsocks in wait mode
Since version 2.5 the master is automatically re-executed in wait-mode
when the config is successfully loaded, puting corner cases of the wait
mode in plain sight.

When using the -x argument and with the right timing, the master will
try to get the FDs again in wait mode even through it's not needed
anymore, which will harm the worker by removing its listeners.

However, if it fails, (and it's suppose to, sometimes), the
master will exit with EXIT_FAILURE because it does not have the
MODE_MWORKER flag, but only the MODE_MWORKER_WAIT flag. With the
consequence of killing the workers.

This patch fixes the issue by restricting the use of _getsocks to some
modes.

This patch must be backported in every version supported, even through
the impact should me more harmless in version prior to 2.5.
2022-01-07 18:44:27 +01:00
Frédéric Lécaille
99942d6f4c MINOR: quic: Non-optimal use of a TX buffer
When full, after having reset the writer index, let's reuse the TX buffer in
any case.
2022-01-07 17:58:26 +01:00
Frédéric Lécaille
f010f0aaf2 MINOR: quic: Missing retransmission from qc_prep_fast_retrans()
In fact we must look for the first packet with some ack-elicting frame to
in the packet number space tree to retransmit from. Obviously there
may be already retransmit packets which are not deemed as lost and
still present in the packet number space tree for TX packets.
2022-01-07 17:58:26 +01:00
Frédéric Lécaille
d4ecf94827 MINOR: quic: Only one CRYPTO frame by encryption level
When receiving CRYPTO data from the TLS stack, concatenate the CRYPTO data
to the first allocated CRYPTO frame if present. This reduces by one the number
of handshake packets built for a connection with a standard size certificate.
2022-01-07 17:58:26 +01:00
Ilya Shipitsin
37d3e38130 CLEANUP: assorted typo fixes in the code and comments
This is 30th iteration of typo fixes
2022-01-07 14:42:54 +01:00
David CARLIER
df91cbd584 MINOR: cpuset: switch to sched_setaffinity for FreeBSD 14 and above.
Following up previous update on cpuset-t.h. Ultimately, at some point
 the cpuset_setaffinity code path could be removed.
2022-01-07 06:53:51 +01:00
William Dauchy
a9dd901143 MINOR: proxy: add option idle-close-on-response
Avoid closing idle connections if a soft stop is in progress.

By default, idle connections will be closed during a soft stop. In some
environments, a client talking to the proxy may have prepared some idle
connections in order to send requests later. If there is no proper retry
on write errors, this can result in errors while haproxy is reloading.
Even though a proper implementation should retry on connection/write
errors, this option was introduced to support back compat with haproxy <
v2.4. Indeed before v2.4, we were waiting for a last request to be able
to add a "connection: close" header and advice the client to close the
connection.

In a real life example, this behavior was seen in AWS using the ALB in
front of a haproxy. The end result was ALB sending 502 during haproxy
reloads.
This patch was tested on haproxy v2.4, with a regular reload on the
process, and a constant trend of requests coming in. Before the patch,
we see regular 502 returned to the client; when activating the option,
the 502 disappear.

This patch should help fixing github issue #1506.
In order to unblock some v2.3 to v2.4 migraton, this patch should be
backported up to v2.4 branch.

Signed-off-by: William Dauchy <wdauchy@gmail.com>
[wt: minor edits to the doc to mention other options to care about]
Signed-off-by: Willy Tarreau <w@1wt.eu>
2022-01-06 09:09:51 +01:00
Frédéric Lécaille
6b6631593f MINOR: quic: Re-arm the PTO timer upon datagram receipt
When block by the anti-amplification limit, this is the responsability of the
client to unblock it sending new datagrams. On the server side, even if not
well parsed, such datagrams must trigger the PTO timer arming.
2022-01-04 17:30:00 +01:00
Frédéric Lécaille
078634d126 MINOR: quic: PTO timer too often reset
It must be reset when the anti-amplication was reached but only if the
peer address was not validated.
2022-01-04 17:30:00 +01:00
Frédéric Lécaille
41a076087b MINOR: quic: Flag asap the connection having reached the anti-amplification limit
The best location to flag the connection is just after having built the packet
which reached the anti-amplication limit.
2022-01-04 17:30:00 +01:00
Frédéric Lécaille
de6f7c503e MINOR: quic: Prepare Handshake packets asap after completed handshake
Switch back to QUIC_HS_ST_SERVER_HANDSHAKE state after a completed handshake
if acks must be send.
Also ensure we build post handshake frames only one time without using prev_st
variable and ensure we discard the Handshake packet number space only one time.
2022-01-04 17:30:00 +01:00
Frédéric Lécaille
917a7dbdc7 MINOR: quic: Do not drop secret key but drop the CRYPTO data
We need to be able to decrypt late Handshake packets after the TLS secret
keys have been discarded. If not the peer send Handshake packet which have
not been acknowledged. But for such packets, we discard the CRYPTO data.
2022-01-04 17:30:00 +01:00
Frédéric Lécaille
ee2b8b377f MINOR: quic: Improve qc_prep_pkts() flexibility
We want to be able to choose the encryption levels to be used
by qc_prep_pkts() outside of it.
2022-01-04 17:30:00 +01:00
Frédéric Lécaille
f7ef97698a MINOR: quic: Comment fix.
When we drop a packet with unknown length, this is the entire datagram which
must be skipped.
2022-01-04 17:30:00 +01:00
Frédéric Lécaille
a56054e438 MINOR: quic: Probe several packet number space upon timer expiration
When the loss detection timer expires, we SHOULD include new data in
our probing packets (RFC 9002 par 6.2.4. Sending Probe Packets).
2022-01-04 17:30:00 +01:00
Frédéric Lécaille
db6a4727cf MINOR: quic: Probe Initial packet number space more often
Especially when the PTO expires for Handshake packet number space and when
Initial packets are still flying (for QUIC servers).
2022-01-04 17:30:00 +01:00
Frédéric Lécaille
3bb457c4ba MINOR: quic: Speeding up Handshake Completion
According to RFC 9002 par. 6.2.3. when receving duplicate Initial CRYPTO
data a server may a packet containing non unacknowledged before the PTO
expiry.
2022-01-04 17:30:00 +01:00
Frédéric Lécaille
63556772cc MINOR: quic: qc_prep_pkts() code moving
Move the switch default case code out of the switch to improve the readibily.
2022-01-04 17:30:00 +01:00
Frédéric Lécaille
5732062cd2 MINOR: quic: Useless test in qc_prep_pkts()
These tests were there to initiate PTO probing but they are not correct.
Furthermore they may break the PTO probing process and lead to useless packet
building.
2022-01-04 17:30:00 +01:00
Frédéric Lécaille
dd51da599e MINOR: quic: Wrong packet number space trace in qc_prep_pkts()
It was always the first packet number space information which was dumped.
2022-01-04 17:30:00 +01:00
Frédéric Lécaille
466e9da145 MINOR: quic: Remove nb_pto_dgrams quic_conn struct member
For now on we rely on tx->pto_probe pktns struct member to inform
the packet building function we want to probe.
2022-01-04 17:30:00 +01:00
Frédéric Lécaille
22576a2e55 MINOR: quic: Wrong ack_delay compution before calling quic_loss_srtt_update()
RFC 9002 5.3. Estimating smoothed_rtt and rttvar:
MUST use the lesser of the acknowledgment delay and the peer's max_ack_delay
after the handshake is confirmed.
2022-01-04 17:30:00 +01:00
Frédéric Lécaille
dc90c07715 MINOR: quic: Wrong loss time computation in qc_packet_loss_lookup()
This part as been modified by the RFC since our first implementation.
2022-01-04 17:30:00 +01:00
Frédéric Lécaille
22cfd83890 MINOR: quic: Add trace about in flight bytes by packet number space
This parameter is useful to diagnose packet loss detection issues.
2022-01-04 17:30:00 +01:00
Frédéric Lécaille
fde2a98dd1 MINOR: quic: Wrong traces after rework
TRACE_*() macros must take a quic_conn struct as first argument.
2022-01-04 17:30:00 +01:00
Christopher Faulet
7bf46bb9a9 BUG/MEDIUM: http-ana: Preserve response's FLT_END analyser on L7 retry
When a filter is attached on a stream, the FLT_END analyser must not be
removed from the response channel on L7 retry. It is especially important
because CF_FLT_ANALYZE flag is still set. This means the synchronization
between the two sides when the filter ends can be blocked. Depending on the
timing, this can freeze the stream infinitely or lead to a spinning loop.

Note that the synchronization between the two sides at the end of the
analysis was introduced because the stream was reused in HTTP between two
transactions. But, since the HTX was introduced, a new stream is created for
each transaction. So it is probably possible to remove this step for 2.2 and
higher.

This patch must be backported as far as 2.0.
2022-01-04 10:56:04 +01:00
David Carlier
ae5c42f4d0 BUILD/MINOR: tools: solaris build fix on dladdr.
dladdr takes a mutable address on this platform.
2022-01-03 14:43:51 +01:00
Ilya Shipitsin
5e87bcf870 CLEANUP: assorted typo fixes in the code and comments This is 29th iteration of typo fixes 2022-01-03 14:40:58 +01:00
Willy Tarreau
1513c5479a MEDIUM: pools: release cached objects in batches
With this patch pool_evict_last_items builds clusters of up to
CONFIG_HAP_POOL_CLUSTER_SIZE entries so that accesses to the shared
pools are reduced by CONFIG_HAP_POOL_CLUSTER_SIZE and the inter-
thread contention is reduced by as much..
2022-01-02 19:35:26 +01:00
Willy Tarreau
43937e920f MEDIUM: pools: start to batch eviction from local caches
Since previous patch we can forcefully evict multiple objects from the
local cache, even when evicting basd on the LRU entries. Let's define
a compile-time configurable setting to batch releasing of objects. For
now we set this value to 8 items per round.

This is marked medium because eviction from the LRU will slightly change
in order to group the last items that are freed within a single cache
instead of accurately scanning only the oldest ones exactly in their
order of appearance. But this is required in order to evolve towards
batched removals.
2022-01-02 19:35:26 +01:00
Willy Tarreau
a0b5831eed MEDIUM: pools: centralize cache eviction in a common function
We currently have two functions to evict cold objects from local caches:
pool_evict_from_local_cache() to evict from a single cache, and
pool_evict_from_local_caches() to evict oldest objects from all caches.

The new function pool_evict_last_items() focuses on scanning oldest
objects from a pool and releasing a predefined number of them, either
to the shared pool or to the system. For now they're evicted one at a
time, but the next step will consist in creating clusters.
2022-01-02 19:35:26 +01:00
Willy Tarreau
337410c5a4 MINOR: pools: pass the objects count to pool_put_to_shared_cache()
This is in order to let the caller build the cluster of items to be
released. For now single items are released hence the count is always
1.
2022-01-02 19:35:26 +01:00
Willy Tarreau
148160b027 MINOR: pools: prepare pool_item to support chained clusters
In order to support batched allocations and releases, we'll need to
prepare chains of items linked together and that can be atomically
attached and detached at once. For this we implement a "down" pointer
in each pool_item that points to the other items belonging to the same
group. For now it's always NULL though freeing functions already check
them when trying to release everything.
2022-01-02 19:35:26 +01:00
Willy Tarreau
361e31e3fe MEDIUM: pool: compute the number of evictable entries once per pool
In pool_evict_from_local_cache() we used to check for room left in the
pool for each and every object. Now we compute the value before entering
the loop and keep into a local list what has to be released, and call
the OS-specific functions for the other ones.

It should already save some cycles since it's not needed anymore to
recheck for the pool's filling status. But the main expected benefit
comes from the ability to pre-construct a list of all releasable
objects, that will later help with grouping them.
2022-01-02 19:35:26 +01:00
Willy Tarreau
c16ed3b090 MINOR: pool: introduce pool_item to represent shared pool items
In order to support batch allocation from/to shared pools, we'll have to
support a specific representation for pool objects. The new pool_item
structure will be used for this. For now it only contains a "next"
pointer that matches exactly the current storage model. The few functions
that deal with the shared pool entries were adapted to use the new type.
There is no functionality difference at this point.
2022-01-02 19:35:26 +01:00
Willy Tarreau
b46674a283 MINOR: pool: check for pool's fullness outside of pool_put_to_shared_cache()
Instead of letting pool_put_to_shared_cache() pass the object to the
underlying OS layer when there's no more room, let's have the caller
check if the pool is full and either call pool_put_to_shared_cache()
or call pool_free_nocache().

Doing this sensibly simplifies the code as this function now only has
to deal with a pool and an item and only for cases where there are
local caches and shared caches. As the code was simplified and the
calls more isolated, the function was moved to pool.c.

Note that it's only called from pool_evict_from_local_cache{,s}() and
that a part of its logic might very well move there when dealing with
batches.
2022-01-02 19:35:26 +01:00
Willy Tarreau
afe2c4a1fc MINOR: pool: allocate from the shared cache through the local caches
One of the thread scaling challenges nowadays for the pools is the
contention on the shared caches. There's never any situation where we
have a shared cache and no local cache anymore, so we can technically
afford to transfer objects from the shared cache to the local cache
before returning them to the user via the regular path. This adds a
little bit more work per object per miss, but will permit batch
processing later.

This patch simply moves pool_get_from_shared_cache() to pool.c under
the new name pool_refill_local_from_shared(), and this function does
not return anything but it places the allocated object at the head of
the local cache.
2022-01-02 19:27:57 +01:00
Willy Tarreau
8c4927098e CLEANUP: pools: get rid of the POOL_LINK macro
The POOL_LINK macro is now only used for debugging, and it still requires
ifdefs around, which needlessly complicates the code. Let's replace it
and the calling code with a new pair of macros: POOL_DEBUG_SET_MARK()
and POOL_DEBUG_CHECK_MARK(), that respectively store and check the pool
pointer in the extra location at the end of the pool. This removes 4
pairs of ifdefs in the middle of the code.
2022-01-02 12:44:19 +01:00
Willy Tarreau
799f6143ca CLEANUP: pools: do not use the extra pointer to link shared elements
This practice relying on POOL_LINK() dates from the era where there were
no pool caches, but given that the structures are a bit more complex now
and that pool caches do not make use of this feature, it is totally
useless since released elements have already been overwritten, and yet
it complicates the architecture and prevents from making simplifications
and optimizations. Let's just get rid of this feature. The pointer to
the origin pool is preserved though, as it helps detect incorrect frees
and serves as a canary for overflows.
2022-01-02 12:44:19 +01:00
Willy Tarreau
d5ec100661 MINOR: pools: always evict oldest objects first in pool_evict_from_local_cache()
For an unknown reason, despite the comment stating that we were evicting
oldest objects first from the local caches, due to the use of LIST_NEXT,
the newest were evicted, since pool_put_to_cache() uses LIST_INSERT().

Some tests on 16 threads show that evicting oldest objects instead can
improve performance by 0.5-1% especially when using shared pools.
2022-01-02 12:40:14 +01:00
William Lallemand
e69563fd8e BUG/MEDIUM: ssl: free the ckch instance linked to a server
This patch unlinks and frees the ckch instance linked to a server during
the free of this server.

This could have locked certificates in a "Used" state when removing
servers dynamically from the CLI. And could provoke a segfault once we
try to dynamically update the certificate after that.

This must be backported as far as 2.4.
2021-12-30 16:56:52 +01:00
William Lallemand
231610ad9c BUG/MINOR: ssl: free the fields in srv->ssl_ctx
A lot of free are missing in ssl_sock_free_srv_ctx(), this could result
in memory leaking when removing dynamically a server via the CLI.

This must be backported in every branches, by removing the fields that
does not exist in the previous branches.
2021-12-30 13:43:04 +01:00
William Lallemand
2c776f1c30 BUG/MEDIUM: ssl: initialize correctly ssl w/ default-server
This bug was introduced by d817dc73 ("MEDIUM: ssl: Load client
certificates in a ckch for backend servers") in which the creation of
the SSL_CTX for a server was moved to the configuration parser when
using a "crt" keyword instead of being done in ssl_sock_prepare_srv_ctx().

The patch 0498fa40 ("BUG/MINOR: ssl: Default-server configuration ignored by
server") made it worse by setting the same SSL_CTX for every servers
using a default-server. Resulting in any SSL option on a server applied
to every server in its backend.

This patch fixes the issue by reintroducing a string which store the
path of certificate inside the server structure, and loading the
certificate in ssl_sock_prepare_srv_ctx() again.

This is a quick fix to backport, a cleaner way can be achieve by always
creating the SSL_CTX in ssl_sock_prepare_srv_ctx() and splitting
properly the ssl_sock_load_srv_cert() function.

This patch fixes issue #1488.

Must be backported as far as 2.4.
2021-12-29 14:42:16 +01:00
Willy Tarreau
654726db5a MINOR: debug: add support for -dL to dump library names at boot
This is a second help to dump loaded library names late at boot, once
external code has already been initialized. The purpose is to provide
a format that makes it easy to pass to "tar" to produce an archive
containing the executable and the list of dependencies. For example
if haproxy is started as "haproxy -f foo.cfg", a config check only
will suffice to quit before starting, "-q" will be used to disable
undesired output messages, and -dL will be use to dump libraries.
This will result in such a command to trivially produce a tarball
of loaded libraries:

   ./haproxy -q -c -dL -f foo.cfg | tar -T - -hzcf archive.tgz
2021-12-28 17:07:13 +01:00
Willy Tarreau
6ab7b21a11 MINOR: debug: add ability to dump loaded shared libraries
Many times core dumps reported by users who experience trouble are
difficult to exploit due to missing system libraries. Sometimes,
having just a list of loaded libraries and their respective addresses
can already provide some hints about some problems.

This patch makes a step in that direction by adding a new "show libs"
command that will try to enumerate the list of object files that are
loaded in memory, relying on the dynamic linker for this. It may also
be used to detect that some foreign code embarks other undesired libs
(e.g. some external Lua modules).

At the moment it's only supported on glibc when USE_DL is set, but it's
implemented in a way that ought to make it reasonably easy to be extended
to other platforms.
2021-12-28 16:59:00 +01:00
Willy Tarreau
b4ff6f4ae9 BUG/MEDIUM: peers: properly skip conn_cur from incoming messages
The approach used for skipping conn_cur in commit db2ab8218 ("MEDIUM:
stick-table: never learn the "conn_cur" value from peers") was wrong,
it only works with simple tables but as soon as frequency counters or
arrays are exchanged after conn_cur, the stream is desynchronized and
incorrect values are read. This is because the fields have a variable
length depending on their types and cannot simply be skipped by a
"continue" statement.

Let's change the approach to make sure we continue to completely parse
these local-only fields, and only drop the value at the moment we're
about to store them, since this is exactly the intent.

A simpler approach could consist in having two sets of stktable_data_ptr()
functions, one for retrieval and one for storage, and to make the store
function return a NULL pointer for local types. For now this doesn't
seem worth the trouble.

This fixes github issue #1497. Thanks to @brenc for the reproducer.

This must be backported to 2.5.
2021-12-24 13:48:39 +01:00
Willy Tarreau
266d540549 BUG/MEDIUM: backend: fix possible sockaddr leak on redispatch
A subtle change of target address allocation was introduced with commit
68cf3959b ("MINOR: backend: rewrite alloc of stream target address") in
2.4. Prior to this patch, a target address was allocated by function
assign_server_address() only if none was previously allocated. After
the change, the allocation became unconditional. Most of the time it
makes no difference, except when we pass multiple times through
connect_server() with SF_ADDR_SET cleared.

The most obvious fix would be to avoid allocating that address there
when already set, but the root cause is that since introduction of
dynamically allocated addresses, the SF_ADDR_SET flag lies. It can
be cleared during redispatch or during a queue redistribution without
the address being released.

This patch instead gives back all its correct meaning to SF_ADDR_SET
and guarantees that when not set no address is allocated, by freeing
that address at the few places the flag is cleared. The flag could
even be removed so that only the address is checked but that would
require to touch many areas for no benefit.

The easiest way to test it is to send requests to a proxy with l7
retries enabled, which forwards to a server returning 500:

  defaults
    mode http
    timeout client 1s
    timeout server 1s
    timeout connect 1s
    retry-on all-retryable-errors
    retries 1
    option redispatch

  listen proxy
    bind *:5000
    server app 0.0.0.0:5001

  frontend dummy-app
    bind :5001
    http-request return status 500

Issuing "show pools" on the CLI will show that pool "sockaddr" grows
as requests are redispatched, and remains stable with the fix. Even
"ps" will show that the process' RSS grows by ~160B per request.

This fix will need to be backported to 2.4. Note that before 2.5,
there's no strm->si[1].dst, strm->target_addr must be used instead.

This addresses github issue #1499. Special thanks to Daniil Leontiev
for providing a well-documented reproducer.
2021-12-24 11:50:01 +01:00
Amaury Denoyelle
9979d0d1ea BUG/MINOR: quic: fix potential use of uninit pointer
Properly initialized the ssl_sock_ctx pointer in qc_conn_init. This is
required to avoid to set an undefined pointer in qc.xprt_ctx if argument
*xprt_ctx is NULL.
2021-12-23 16:33:47 +01:00
Amaury Denoyelle
c6fab98f9b BUG/MINOR: quic: fix potential null dereference
This is not a real issue because found_in_dcid can not be set if qc is
NULL.
2021-12-23 16:32:19 +01:00
Amaury Denoyelle
76f47caacc MEDIUM: quic: implement refcount for quic_conn
Implement a refcount on quic_conn instance. By default, the refcount is
0. Two functions are implemented to manipulate it.
* qc_conn_take() which increments the refcount
* qc_conn_drop() which decrements it. If the refcount is 0 *BEFORE*
  the substraction, the instance is freed.

The refcount is incremented on retrieve_qc_conn_from_cid() or when
allocating a new quic_conn in qc_lstnr_pkt_rcv(). It is substracted most
notably by the xprt.close operation and at the end of
qc_lstnr_pkt_rcv(). The increments/decrements should be conducted under
the CID lock to guarantee thread-safety.
2021-12-23 16:06:07 +01:00
Amaury Denoyelle
0a29e13835 MINOR: quic: delete timer task on quic_close()
The timer task is attached to the connection-pinned thread. Only this
thread can delete it. With the future refcount implementation of
quic_conn, every thread can be responsible to remove the quic_conn via
quic_conn_free(). Thus, the timer task deletion is moved from the
calling function quic_close().
2021-12-23 16:06:07 +01:00
Amaury Denoyelle
e81fed9a54 MINOR: quic: replace usage of ssl_sock_ctx by quic_conn
Big refactoring on xprt-quic. A lot of functions were using the
ssl_sock_ctx as argument to only access the related quic_conn. All these
arguments are replaced by a quic_conn parameter.

As a convention, the quic_conn instance is always the first parameter of
these functions.

This commit is part of the rearchitecture of xprt-quic layers and the
separation between xprt and connection instances.
2021-12-23 16:06:06 +01:00
Amaury Denoyelle
741eacca47 MINOR: quic: remove unnecessary if in qc_pkt_may_rm_hp()
Remove the shortcut to use the INITIAL encryption level when removing
header protection on first connection packet.

This change is useful for the following change which removes
ssl_sock_ctx in argument lists in favor of the quic_conn instance.
2021-12-23 16:02:24 +01:00
Amaury Denoyelle
7ca7c84fb8 MINOR: quic: store ssl_sock_ctx reference into quic_conn
Add a pointer in quic_conn to its related ssl_sock_ctx. This change is
required to avoid to use the connection instance to access it.

This commit is part of the rearchitecture of xprt-quic layers and the
separation between xprt and connection instances. It will be notably
useful when the connection allocation will be delayed.
2021-12-23 15:51:00 +01:00
Amaury Denoyelle
a83729e9e6 MINOR: quic: remove unnecessary call to free_quic_conn_cids()
free_quic_conn_cids() was called in quic_build_post_handshake_frames()
if an error occured. However, the only error is an allocation failure of
the CID which does not required to call it.

This change is required for future refcount implementation. The CID lock
will be removed from the free_quic_conn_cids() and to the caller.
2021-12-23 15:51:00 +01:00
Amaury Denoyelle
250ac42754 BUG/MINOR: quic: upgrade rdlock to wrlock for ODCID removal
When a quic_conn is found in the DCID tree, it can be removed from the
first ODCID tree. However, this operation must absolutely be run under a
write-lock to avoid race condition. To avoid to use the lock too
frequently, node.leaf_p is checked. This value is set to NULL after
ebmb_delete.
2021-12-23 15:51:00 +01:00
Amaury Denoyelle
d6b166787c REORG: quic: remove qc_ prefix on functions which not used it directly
The qc_* prefix should be reserved to functions which used a specific
quic_conn instance and are expected to be pinned on the connection
thread.
2021-12-23 15:51:00 +01:00
Frédéric Lécaille
010e532e81 MINOR: quic: Add CONNECTION_CLOSE phrase to trace
Some applications may send some information about the reason why they decided
to close a connection. Add them to CONNECTION_CLOSE frame traces.
Take the opportunity of this patch to shorten some too long variable names
without any impact.
2021-12-23 15:48:25 +01:00
Frédéric Lécaille
1ede823d6b MINOR: quic: Add traces for RX frames (flow control related)
Add traces about important frame types to chunk_tx_frm_appendf()
and call this function for any type of frame when parsing a packet.
Move it to quic_frame.c
2021-12-23 15:48:25 +01:00
Willy Tarreau
77bfa66124 DEBUG: ssl: make sure we never change a servername on established connections
Since this case was already met previously with commit 655dec81b
("BUG/MINOR: backend: do not set sni on connection reuse"), let's make
sure that we don't change reused connection settings. This could be
generalized to most settings that are only in effect before the handshake
in fact (like set_alpn and a few other ones).
2021-12-23 15:44:06 +01:00
Willy Tarreau
0d93a81863 MINOR: pools: work around possibly slow malloc_trim() during gc
During 2.4-dev, support for malloc_trim() was implemented to ease
release of memory in a stopping process. This was found to be quite
effective and later backported to 2.3.7.

Then it was found that sometimes malloc_trim() could take a huge time
to complete it if was competing with other threads still allocating and
releasing memory, reason why it was decided in 2.5-dev to move
malloc_trim() under the thread isolation that was already in place in
the shared pool version of pool_gc() (this was commit 26ed1835).

However, other instances of pool_gc() that used to call malloc_trim()
were not updated since they were not using thread isolation. Currently
we have two other such instances, one for when there is absolutely no
pool and one for when there are only thread-local pools.

Christian Ruppert reported in GH issue #1490 that he's sometimes seeing
and old process die upon reload when upgrading from 2.3 to 2.4, and
that this happens inside malloc_trim(). The problem is that since
2.4-dev11 with commit 0bae07592 we detect modern libc that provide a
faster thread-aware allocator and do not maintain shared pools anymore.
As such we're using again the simpler pool_gc() implementations that do
not use thread isolation around the malloc_trim() call.

All this code was cleaned up recently and the call moved to a new
function trim_all_pools(). This patch implements explicit thread isolation
inside that function so that callers do not have to care about this
anymore. The thread isolation is conditional so that this doesn't affect
the one already in place in the larger version of pool_gc(). This way it
will solve the problem for all callers.

This patch must be backported as far as 2.3. It may possibly require
some adaptations. If trim_all_pools() is not present, copy-pasting the
tests in each version of pool_gc() will have the same effect.

Thanks to Christian for his detailed report and his testing.
2021-12-23 15:44:06 +01:00
Frédéric Lécaille
2c15a66b61 MINOR: quic: Drop asap Retry or Version Negotiation packets
These packet are only sent by servers. We drop them as soon as possible
when we are an haproxy listener.
2021-12-22 20:43:22 +01:00
Frédéric Lécaille
e7ff2b265a MINOR: quic: xprt traces fixes
Empty parameters are permitted with TRACE_*() macros. If removed, must
be replaced by NULL.
2021-12-22 20:43:22 +01:00
Frédéric Lécaille
10250b2e93 MINOR: quic: Handle the cases of overlapping STREAM frames
This is the same treatment for bidi and uni STREAM frames. This is a duplication
code which should me remove building a function for both these types of streams.
2021-12-22 20:43:22 +01:00
Frédéric Lécaille
01cfec74f5 MINOR: quic: Wrong dropped packet skipping
There were cases where some dropped packets were not well skipped. This led
the low level QUIC packet parser to continue from wrong packet boundaries.
2021-12-22 20:43:22 +01:00
Frédéric Lécaille
4d118d6a8e MINOR: quic: unchecked qc_retrieve_conn_from_cid() returned value
If qc_retrieve_conn_from_cid() did not manage to retrieve the connection
from packet CIDs, we must drop them.
2021-12-22 17:27:51 +01:00
Frédéric Lécaille
677b99dca7 MINOR: quic: Add stream IDs to qcs_push_frame() traces
This is only for debug purpose.
2021-12-21 16:06:03 +01:00
Amaury Denoyelle
e770ce3980 MINOR: quic: add quic_conn instance in traces for qc_new_conn
The connection instance has been replaced by a quic_conn as first
argument to QUIC traces. It is possible to report the quic_conn instance
in the qc_new_conn(), contrary to the connection which is not
initialized at this stage.
2021-12-21 15:53:19 +01:00
Amaury Denoyelle
7aaeb5b567 MINOR: quic: use quic_conn as argument to traces
Replace the connection instance for first argument of trace callback by
a quic_conn instance. The QUIC trace module is properly initialized with
the first argument refering to a quic_conn.

Replace every connection instances in TRACE_* macros invocation in
xprt-quic by its related quic_conn. In some case, the connection is
still used to access the quic_conn. It may cause some problem on the
future when the connection will be completly separated from the xprt
layer.

This commit is part of the rearchitecture of xprt-quic layers and the
separation between xprt and connection instances.
2021-12-21 15:53:19 +01:00
Amaury Denoyelle
baea96400f MINOR: trace: add quic_conn argument definition
Prepare trace support for quic_conn instances as argument. This will be
used by the xprt-quic layer in replacement of the connection.

This commit is part of the rearchitecture of xprt-quic layers and the
separation between xprt and connection instances.
2021-12-21 15:53:19 +01:00
Amaury Denoyelle
4fd53d772f MINOR: quic: add const qualifier for traces function
Add const qualifier on arguments of several dump functions used in the
trace callback. This is required to be able to replace the first trace
argument by a quic_conn instance. The first argument is a const pointer
and so the members accessed through it must also be const.
2021-12-21 15:53:19 +01:00
Amaury Denoyelle
c15dd9214b MINOR: quic: add reference to quic_conn in ssl context
Add a new member in ssl_sock_ctx structure to reference the quic_conn
instance if used in the QUIC stack. This member is initialized during
qc_conn_init().

This is needed to be able to access to the quic_conn without relying on
the connection instance. This commit is part of the rearchitecture of
xprt-quic layers and the separation between xprt and connection
instances.
2021-12-21 15:53:19 +01:00
Amaury Denoyelle
8a5b27a9b9 REORG: quic: move mux function outside of xprt
Move qcc_get_qcs() function from xprt_quic.c to mux_quic.c. This
function is used to retrieve the qcs instance from a qcc with a stream
id. This clearly belongs to the mux-quic layer.
2021-12-21 15:51:40 +01:00
Amaury Denoyelle
17a741693c CLEANUP: quic: rename quic_conn instances to qc
Use the convention of naming quic_conn instance as qc to not confuse it
with a connection instance. The changes occured for qc_parse_pkt_frms(),
qc_build_frms() and qc_do_build_pkt().
2021-12-21 15:51:30 +01:00
Frédéric Lécaille
2ce5acf7ed MINOR: quic: Wrong packet refcount handling in qc_pkt_insert()
The QUIC connection I/O handler qc_conn_io_cb() could be called just after
qc_pkt_insert() have inserted a packet in a its tree, and before qc_pkt_insert()
have incremented the reference counter to this packet. As qc_conn_io_cb()
decrement this counter, the packet could be released before qc_pkt_insert()
might increment the counter, leading to possible crashes when trying to do so.
So, let's make qc_pkt_insert() increment this counter before inserting the packet
it is tree. No need to lock anything for that.
2021-12-20 17:33:51 +01:00
Frédéric Lécaille
f1d38cbe15 MINOR: quic: Do not forget STREAM frames received in disorder
Add a function to process all STREAM frames received and ordered
by their offset (qc_treat_rx_strm_frms()) and modify
qc_handle_bidi_strm_frm() consequently.
2021-12-20 17:33:51 +01:00
Frédéric Lécaille
4137b2d316 MINOR: quic: Do not expect to receive only one O-RTT packet
There is nothing about this in the RFC. We must support to receive
several 0-RTT packets before the handshake has completed.
2021-12-20 17:33:51 +01:00
Frédéric Lécaille
91ac6c3a8a MINOR: quic: Add a function to list remaining RX packets by encryption level
This is only to debug some issues which cause the RX buffer saturation
with "Too big packet" traces.
2021-12-20 17:33:51 +01:00
Remi Tricot-Le Breton
cc750efbc5 MINOR: ssl: Remove empty lines from "show ssl ocsp-response" output
There were empty lines in the output of the CLI's "show ssl
ocsp-response" command (after the certificate ID and between two
certificates). This patch removes them since an empty line should mark
the end of the output.

Must be backported in 2.5.
2021-12-20 12:02:17 +01:00
Amaury Denoyelle
dbef985b74 MINOR: quic: simplify the removal from ODCID tree
With the DCID refactoring, the locking is more centralized. It is
possible to simplify the code for removal of a quic_conn from the ODCID
tree.

This operation can be conducted as soon as the connection has been
retrieved from the DCID tree, meaning that the peer now uses the final
DCID. Remove the bit to flag a connection for removal and just uses
ebmb_delete() on each sucessful lookup on the DCID tree. If the
quic_conn has already been removed, it is just a noop thanks to
eb_delete() implementation.
2021-12-17 10:59:36 +01:00
Amaury Denoyelle
8efe032bba MINOR: quic: refactor DCID lookup
A new function named qc_retrieve_conn_from_cid() now contains all the
code to retrieve a connection from a DCID. It handle all type of packets
and centralize the locking on the ODCID/DCID trees.

This simplify the qc_lstnr_pkt_rcv() function.
2021-12-17 10:59:36 +01:00
Amaury Denoyelle
adb2276524 MINOR: quic: compare coalesced packets by DCID
If an UDP datagram contains multiple QUIC packets, they must all use the
same DCID. The datagram context is used partly for this.

To ensure this, a comparison was made on the dcid_node of DCID tree. As
this is a comparison based on pointer address, it can be faulty when
nodes are removed/readded on the same pointer address.

Replace this comparison by a proper comparison on the DCID data itself.
To this end, the dgram_ctx structure contains now a quic_cid member.
2021-12-17 10:59:36 +01:00
Amaury Denoyelle
c92cbfc014 MINOR: quic: refactor concat DCID with address for Initial packets
For first Initial packets, the socket source dest address is
concatenated to the DCID. This is used to be able to differentiate
possible collision between several clients which used the same ODCID.

Refactor the code to manage DCID and the concatenation with the address.
Before this, the concatenation was done on the quic_cid struct and its
<len> field incremented. In the code it is difficult to differentiate a
normal DCID with a DCID + address concatenated.

A new field <addrlen> has been added in the quic_cid struct. The <len>
field now only contains the size of the QUIC DCID. the <addrlen> is
first initialized to 0. If the address is concatenated, it will be
updated with the size of the concatenated address. This now means we
have to explicitely used either cid.len or cid.len + cid.addrlen to
access the DCID or the DCID + the address. The code should be clearer
thanks to this.

The field <odcid_len> in quic_rx_packet struct is now useless and has
been removed. However, a new parameter must be added to the
qc_new_conn() function to specify the size of the ODCID addrlen.
2021-12-17 10:59:36 +01:00
Amaury Denoyelle
d496251cde MINOR: quic: rename constant for haproxy CIDs length
On haproxy implementation, generated DCID are on 8 bytes, the minimal
value allowed by the specification. Rename the constant representing
this size to inform that this is haproxy specific.
2021-12-17 10:59:36 +01:00
Amaury Denoyelle
260e5e6c24 MINOR: quic: add missing lock on cid tree
All operation on the ODCID/DCID trees must be conducted under a
read-write lock. Add a missing read-lock on the lookup operation inside
listener handler.
2021-12-17 10:59:36 +01:00
Amaury Denoyelle
67e6cd50ef CLEANUP: quic: rename quic_conn conn to qc in quic_conn_free
Rename quic_conn from conn to qc to differentiate it from a struct
connection instance. This convention is already used in the majority of
the code.
2021-12-17 10:59:35 +01:00
Amaury Denoyelle
47e1f6d4e2 CLEANUP: quic: fix spelling mistake in a trace
Initiial -> Initial
2021-12-17 10:59:35 +01:00
Amaury Denoyelle
fdbf63e86e MINOR: mux-quic: fix trace on stream creation
Replace non-initialized qcs.by_id.key by the id to report the proper
stream ID on stream creation.
2021-12-17 09:55:01 +01:00
Frédéric Lécaille
8678eb0d19 CLEANUP: quic: Shorten a litte bit the traces in lstnr_rcv_pkt()
Some traces were too long and confusing when displaying 0 for a non-already
parsed packet number.
2021-12-17 08:38:43 +01:00
Frédéric Lécaille
25eeebe293 MINOR: quic: Do not mix packet number space and connection flags
The packet number space flags were mixed with the connection level flags.
This leaded to ACK to be sent at the connection level without regard to
the underlying packet number space. But we want to be able to acknowleged
packets for a specific packet number space.
2021-12-17 08:38:43 +01:00
Frédéric Lécaille
afd373c232 MINOR: hq_interop: Stop BUG_ON() truncated streams
This is required if we do not want to make haproxy crash during zerortt
interop runner test which makes a client open multiple streams with
long request paths.
2021-12-17 08:38:43 +01:00
Frédéric Lécaille
3fe7df877d CLEANUP: quic: Comment fix for qc_strm_cpy()
This function never returns a negative value... hopefully because it returns
a size_t!!!
2021-12-17 08:38:43 +01:00
Frédéric Lécaille
e629cfd96a MINOR: qpack: Missing check for truncated QPACK fields
Decrementing <len> variable without checking could make haproxy crash (on abort)
when printing a huge buffer (with negative length).
2021-12-17 08:38:43 +01:00
Frédéric Lécaille
a5da31d186 MINOR: quic: Make xprt support 0-RTT.
A client sends a 0-RTT data packet after an Initial one in the same datagram.
We must be able to parse such packets just after having parsed the Initial packets.
2021-12-17 08:38:43 +01:00
Frédéric Lécaille
1761fdf0c6 MINOR: ssl_sock: Set the QUIC application from ssl_sock_advertise_alpn_protos.
Make this function call quic_set_app_ops() if the protocol could be negotiated
by the TLS stack.
2021-12-17 08:38:43 +01:00
Frédéric Lécaille
b0bd62db23 MINOR: quic: Add quic_set_app_ops() function
Export the code responsible which set the ->app_ops structure into
quic_set_app_ops() function. It must be called by  the TLS callback which
selects the application (ssl_sock_advertise_alpn_protos) so that
to be able to build application packets after having received 0-RTT data.
2021-12-17 08:38:43 +01:00
Frédéric Lécaille
4015cbb723 MINOR: quic: No TX secret at EARLY_DATA encryption level
The TLS does not provide us with TX secrets after we have provided it
with 0-RTT data. This is logic: the server does not need to send 0-RTT
data. We must skip the section where such secrets are derived if we do not
want to close the connection with a TLS alert.
2021-12-17 08:38:43 +01:00
Frédéric Lécaille
ad3c07ae81 MINOR: quic: Enable TLS 0-RTT if needed
Enable 0-RTT at the TLS context level:
    RFC 9001 4.6.1. Enabling 0-RTT
    Accordingly, the max_early_data_size parameter is repurposed to hold a
    sentinel value 0xffffffff to indicate that the server is willing to accept
    QUIC 0-RTT data.
At the SSL connection level, we must call SSL_set_quic_early_data_enabled().
2021-12-17 08:38:43 +01:00
Frédéric Lécaille
0371cd54d0 CLEANUP: quic: Remove cdata_len from quic_tx_packet struct
This field is no more useful. Modify the traces consequently.
Also initialize ->pn_node.key value to -1, which is an illegal value
for QUIC packet number, and display it in traces if different from -1.
2021-12-17 08:38:43 +01:00
Frédéric Lécaille
d8b8443047 MINOR: quic: Add traces for STOP_SENDING frame and modify others
If not handled by qc_parse_pkt_frms(), the packet which contains it is dropped.
Add only a trace when parsing this frame at this time.
Also modify others to reduce the traces size and have more information about streams.
2021-12-17 08:38:43 +01:00
Frédéric Lécaille
1d2faa24d2 CLEANUP: quic_frame: Remove a useless suffix to STOP_SENDING
This is to be consistent with the other frame names. Adding a _frame
suffixe to STOP_SENDING is useless. We know this is a frame.
2021-12-17 08:38:43 +01:00
Frédéric Lécaille
f57c333ac1 MINOR: quic: Attach timer task to thread for the connection.
This is to avoid races between the connection I/O handler and this task
which share too much variables.
2021-12-17 08:38:43 +01:00
Remi Tricot-Le Breton
0b9e190028 MEDIUM: vars: Enable optional conditions to set-var converter and actions
This patch adds the possibility to add a set of conditions to a set-var
call, be it a converter or an action (http-request or http-response
action for instance). The conditions must all be true for the given
set-var call for the variable to actually be set. If any of the
conditions is false, the variable is left untouched.
The managed conditions are the following : "ifexists", "ifnotexists",
"ifempty", "ifnotempty", "ifset", "ifnotset", "ifgt", "iflt".  It is
possible to combine multiple conditions in a single set-var call since
some of them apply to the variable itself, and some others to the input.

This patch does not change the fact that variables of scope proc are
still created during configuration parsing, regardless of the conditions
that might be added to the set-var calls in which they are mentioned.
For instance, such a line :
    http-request set-var(proc.foo,ifexists) int(5)
would not prevent the creation of the variable during init, and when
actually reaching this line during runtime, the proc.foo variable would
already exist. This is specific to the proc scope.

These new conditions mean that a set-var could "fail" for other reasons
than memory allocation failures but without clearing the contents of the
variable.
2021-12-16 17:31:57 +01:00
Remi Tricot-Le Breton
bb6bc95b1e MINOR: vars: Parse optional conditions passed to the set-var actions
This patch adds the parsing of the optional condition parameters that
can be passed to the set-var and set-var-fmt actions (http as well as
tcp). Those conditions will not be taken into account yet in the var_set
function so conditions passed as parameters will not have any effect.
Since actions do not benefit from the parameter preparsing that
converters have, parsing conditions needed to be done by hand.
2021-12-16 17:31:57 +01:00
Remi Tricot-Le Breton
51899d251c MINOR: vars: Parse optional conditions passed to the set-var converter
This patch adds the parsing of the optional condition parameters that
can be passed to the set-var converter. Those conditions will not be
taken into account yet in the var_set function so conditions passed as
parameters will not have any effect. This is true for any condition
apart from the "ifexists" one that is also used to replace the
VF_UPDATEONLY flag that was used to prevent proc scope variable creation
from a LUA module.
2021-12-16 17:31:55 +01:00
Remi Tricot-Le Breton
25fccd52ac MINOR: vars: Delay variable content freeing in var_set function
When calling var_set on a variable of type string (SMP_T_STR, SMP_T_BIN
or SMP_T_METH), the contents of the variable were freed directly. When
adding conditions to set-var calls we might have cases in which the
contents of an existing variable should be kept unchanged so the freeing
of the internal buffers is delayed in the var_set function (so that we
can bypass it later).
2021-12-16 17:31:31 +01:00
Remi Tricot-Le Breton
1bd9805085 MINOR: vars: Set variable type to ANY upon creation
The type of a newly created variable was not initialized. This patch
sets it to SMP_T_ANY by default. This will be required when conditions
can be added to a set-var call because we might end up creating a
variable without setting it yet.
2021-12-16 17:31:31 +01:00
Remi Tricot-Le Breton
7055301934 MINOR: vars: Move UPDATEONLY flag test to vars_set_ifexist
The vars_set_by_name_ifexist function was created to avoid creating too
many variables from a LUA module. This was made thanks to the
VF_UPDATEONLY flags which prevented variable creation in the var_set
function. Since commit 3a4bedccc ("MEDIUM: vars: replace the global name
index with a hash") this limitation was restricted to 'proc' scope
variables only.
This patch simply moves the scope test to the vars_set_by_name_ifexist
function instead of the var_set function.
2021-12-16 17:31:27 +01:00
David CARLIER
f5d48f8b3b MEDIUM: cfgparse: numa detect topology on FreeBSD.
allowing for all platforms supporting cpu affinity to have a chance
 to detect the cpu topology from a given valid node (e.g.
 DragonflyBSD seems to be NUMA aware from a kernel's perspective
 and seems to be willing start to provide userland means to get
 proper info).
2021-12-15 11:05:51 +01:00
Amaury Denoyelle
b09f4477f4 CLEANUP: cfgparse: modify preprocessor guards around numa detection code
numa_detect_topology() is always define now if USE_CPU_AFFINITY is
activated. For the moment, only on Linux an actual implementation is
provided. For other platforms, it always return 0.

This change has been made to easily add implementation of NUMA detection
for other platforms. The phrasing of the documentation has also been
edited to removed the mention of Linux-only on numa-cpu-mapping
configuration option.
2021-12-15 11:05:51 +01:00
William Lallemand
740629e296 MINOR: cli: "show version" displays the current process version
This patch implements a simple "show version" command which returns
the version of the current process.

It's available from the master and the worker processes, so it is easy
to check if the master and the workers have the same version.

This is a minor patch that really improve compatibility checks
for scripts.

Could be backported in haproxy version as far as 2.0.
2021-12-14 15:40:06 +01:00
Amaury Denoyelle
1ac95445e6 MINOR: hq-interop: refix tx buffering
Incorrect usage of the buffer API : b_room() replaces b_size() to ensure
that we have enough size for http data copy.
2021-12-10 15:14:58 +01:00
William Lallemand
dcbe7b91d6 BUG/MEDIUM: mworker/cli: crash when trying to access an old PID in prompt mode
The master process encounter a crash when trying to access an old
process which left from the master CLI.

To reproduce the problem, you need a prompt to a previous worker, then
wait for this worker to leave, once it left launch a command from this
prompt. The s->target is then filled with a NULL which is dereferenced
when trying to connect().

This patch fixes the problem by checking if s->target is NULL.

Must be backported as far as 2.0.
2021-12-10 14:30:18 +01:00
Amaury Denoyelle
7059ebc095 MINOR: h3: fix possible invalid dereference on htx parsing
The htx variable is only initialized if we have received a HTTP/3
HEADERS frame. Else it must not be dereferenced.

This should fix the compilation on CI with gcc.
  src/h3.c: In function ‘h3_decode_qcs’:
  src/h3.c:224:14: error: ‘htx’ may be used uninitialized in this function
  [-Werror=maybe-uninitialized]
    224 |   htx->flags |= HTX_FL_EOM
2021-12-08 15:52:59 +01:00
Amaury Denoyelle
f3b0ba7dc9 BUG/MINOR: mux-quic: properly initialize flow control
Initialize all flow control members on the qcc instance. Without this,
the value are undefined and it may be possible to have errors about
reached streams limit.
2021-12-08 15:26:16 +01:00
Amaury Denoyelle
5154e7a252 MINOR: quic: notify the mux on CONNECTION_CLOSE
The xprt layer is reponsible to notify the mux of a CONNECTION_CLOSE
reception. In this case the flag QC_CF_CC_RECV is positionned on the
qcc and the mux tasklet is waken up.

One of the notable effect of the QC_CF_CC_RECV is that each qcs will be
released even if they have remaining data in their send buffers.
2021-12-08 15:26:16 +01:00
Amaury Denoyelle
2873a31c81 MINOR: mux-quic: do not release qcs if there is remaining data to send
A qcs is not freed if there is remaining data in its buffer. In this
case, the flag QC_SF_DETACH is positionned.

The qcc io handler is responsible to remove the qcs if the QC_SF_DETACH
is set and their buffers are empty.
2021-12-08 15:26:16 +01:00
Christopher Faulet
70f8948364 BUG/MINOR: cli/server: Don't crash when a server is added with a custom id
When a server is dynamically added via the CLI with a custom id, the key
used to insert it in the backend's tree of used names is not initialized.
The server id must be used but it is only used when no custom id is
provided. Thus, with a custom id, HAProxy crashes.

Now, the server id is always used to init this key, to be able to insert the
server in the corresponding tree.

This patch should fix the issue #1481. It must be backported as far as 2.4.
2021-12-07 19:04:33 +01:00
Christopher Faulet
ba8f06304e MINOR: http-rules: Add capture action to http-after-response ruleset
It is now possible to perform captures on the response when
http-after-response rules are evaluated. It may be handy to capture headers
from responses generated by HAProxy.

This patch is trivial, it may be backported if necessary.
2021-12-07 19:04:33 +01:00
Amaury Denoyelle
db44338473 MINOR: quic: add HTX EOM on request end
Set the HTX EOM flag on RX the app layer. This is required to notify
about the end of the request for the stream analyzers, else the request
channel never goes to MSG_DONE state.
2021-12-07 17:11:22 +01:00
Amaury Denoyelle
fecfa0d822 MINOR: mux-quic: remove uneeded code to check fin on TX
Remove a wrong comparaison with the same buffer on both sides. In any
cases, the FIN is properly set by qcs_push_frame only when the payload
has been totally emptied.
2021-12-07 17:11:22 +01:00
Amaury Denoyelle
5ede40be67 MINOR: hq-interop: fix tx buffering
On h09 app layer, if there is not enought size in the tx buffer, the
transfer is interrupted and the flag QC_SF_BLK_MROOM is positionned.
The transfer is woken up by the mux when new buffer size becomes
available.

This ensure that no data is silently discarded during transfer. Without
this, once the buffer is full the data were removed and thus not send to
the client resulting in a truncating payload.
2021-12-07 17:08:52 +01:00
Frédéric Lécaille
73dcc6ee62 MINOR: quic: Remove QUIC TX packet length evaluation function
Remove qc_eval_pkt() which has come with the multithreading support. It
was there to evaluate the length of a TX packet before building. We could
build from several thread TX packets without consuming a packet number for nothing (when
the building failed). But as the TX packet building functions are always
executed by the same thread, the one attached to the connection, this does
not make sense to continue to use such a function. Furthermore it is buggy
since we had to recently pad the TX packet under certain circumstances.
2021-12-07 15:53:56 +01:00
Frédéric Lécaille
fee7ba673f MINOR: quic: Delete remaining RX handshake packets
After the handshake has succeeded, we must delete any remaining
Initial or Handshake packets from the RX buffer. This cannot be
done depending on the state the connection (->st quic_conn struct
member value) as the packet are not received/treated in order.
2021-12-07 15:53:56 +01:00
Frédéric Lécaille
7d807c93f4 MINOR: quic: QUIC encryption level RX packets race issue
The tree containing RX packets must be protected from concurrent accesses.
2021-12-07 15:53:56 +01:00
Frédéric Lécaille
d61bc8db59 MINOR: quic: Race issue when consuming RX packets buffer
Add a null byte to the end of the RX buffer to notify the consumer there is no
more data to treat.
Modify quic_rx_packet_pool_purge() which is the function which remove the
RX packet from the buffer.
Also rename this function to quic_rx_pkts_del().
As the RX packets may be accessed by the QUIC connection handler (quic_conn_io_cb())
the function responsible of decrementing their reference counters must not
access other information than these reference counters! It was a very bad idea
to try to purge the RX buffer asap when executing this function.
2021-12-07 15:53:56 +01:00
Frédéric Lécaille
f9cb3a9b0e MINOR: quic: RX buffer full due to wrong CRYPTO data handling
Do not leave in the RX buffer packets with CRYPTO data which were
already received. We do this when parsing CRYPTO frame. If already
received we must not consider such frames as if they were not received
in order! This had as side effect to interrupt the transfer of long streams
(ACK frames not parsed).
2021-12-07 15:53:56 +01:00
Amaury Denoyelle
84ea8dcbc4 MEDIUM: mux-quic: handle when sending buffer is full
Handle the case when the app layer sending buffer is full. A new flag
QC_SF_BLK_MROOM is set in this case and the transfer is interrupted. It
is expected that then the conn-stream layer will subscribe to SEND.

The MROOM flag is reset each time the muxer transfer data from the app
layer to its own buffer. If the app layer has been subscribed on SEND it
is woken up.
2021-12-07 15:44:45 +01:00
Amaury Denoyelle
e257d9e8ec MEDIUM: mux-quic: wake up xprt on data transferred
On qc_send, data are transferred for each stream from their qcs.buf to
the qcs.xprt_buf. Wake up the xprt to warn about new data available for
transmission.
2021-12-07 15:44:45 +01:00
Amaury Denoyelle
a2c58a7c8d MEDIUM: mux-quic: subscribe on xprt if remaining data after send
The streams data are transferred from the qcs.buf to the qcs.xprt_buf
during qc_send. If the xprt_buf is not empty and not all data can be
transferred, subscribe the connection on the xprt for sending.

The mux will be woken up by the xprt when the xprt_buf will be cleared.
This happens on ACK reception.
2021-12-07 15:44:45 +01:00
Amaury Denoyelle
a3f222dc1e MINOR: mux-quic: implement subscribe on stream
Implement the subscription in the mux on the qcs instance.

Subscribe is now used by the h3 layer when receiving an incomplete frame
on the H3 control stream. It is also used when attaching the remote
uni-directional streams on the h3 layer.

In the qc_send, the mux wakes up the qcs for each new transfer executed.
This is done via the method qcs_notify_send().

The xprt wakes up the qcs when receiving data on unidirectional streams.
This is done via the method qcs_notify_recv().
2021-12-07 15:44:45 +01:00
Amaury Denoyelle
c2025c1ec6 MEDIUM: quic: detect the stream FIN
Set the QC_SF_FIN_STREAM on the app layers (h3 / hq-interop) when
reaching the HTX EOM. This is used to warn the mux layer to set the FIN
on the QUIC stream.
2021-12-07 15:44:45 +01:00
Amaury Denoyelle
916f0ac1e7 MEDIUM: mux-quic: implement release mux operation
Implement qc_release. This function is called by the upper layer on
connection close. For the moment, this only happens on client timeout.

This functions is used the free a qcs instance. If all bidirectional
streams are freed, the qcc instance and the connection are purged.
2021-12-07 15:44:45 +01:00
Amaury Denoyelle
deed777766 MAJOR: mux-quic: implement a simplified mux version
Re-implement the QUIC mux. It will reuse the mechanics from the previous
mux without all untested/unsupported features. This should ease the
maintenance.

Note that a lot of features are broken for the moment. They will be
re-implemented on the following commits to have a clean commit history.
2021-12-07 15:44:45 +01:00
Amaury Denoyelle
d1202edadd MINOR: h3: remove duplicated FIN flag position
The FIN flag is already set in h3_snd_buf on HTX EOM reception. The same
action in h3_resp_headers_send is duplicated and thus now removed.
2021-12-07 15:37:53 +01:00
Amaury Denoyelle
e2288c3087 MEDIUM: xprt-quic: finalize app layer initialization after ALPN nego
The app layer is initialized after the handshake completion by the XPRT
stack. Call the finalize operation just after that.

Remove the erroneous call to finalize by the mux in the TPs callback as
the app layer is not yet initialized at this stage.

This should fix the missing H3 settings currently not emitted by
haproxy.
2021-12-07 15:37:53 +01:00
Amaury Denoyelle
e1f3ff0d08 MINOR: h3: add BUG_ON on control receive function
Add BUG_ON statement when handling a non implemented frames on the
control stream. This is required because frames must be removed from the
RX buffer or else it will stall the buffer.
2021-12-07 15:37:53 +01:00
Amaury Denoyelle
942fc79b5f MINOR: quic: fix segfault on CONNECTION_CLOSE parsing
At the moment the reason_phrase member of a
quic_connection_close/quic_connection_close_app structure is not
allocated. Comment the memcpy to it to avoid segfault.
2021-12-07 15:37:53 +01:00
Willy Tarreau
b154422db1 IMPORT: slz: use the correct CRC32 instruction when running in 32-bit mode
Many ARMv8 processors also support Aarch32 and can run armv7 and even
thumb2 code. While armv8 compilers will not emit these instructions,
armv7 compilers that are aware of these processors will do. For
example, using gcc built for an armv7 target and passing it
"-mcpu=cortex-a72" or "-march=armv8-a+crc" will result in the CRC32
instruction to be used.

In this case the current assembly code fails because with the ARM and
Thumb2 instruction sets there is no such "%wX" half-registers. We need
to use "%X" instead as the native 32-bit register when running with a
32-bit instruction set, and use "%wX" when using the 64-bit instruction
set (A64).

This is slz upstream commit fab83248612a1e8ee942963fe916a9cdbf085097
2021-12-06 09:14:20 +01:00
Willy Tarreau
88bc800eae BUILD: tree-wide: avoid warnings caused by redundant checks of obj_types
At many places we use construct such as:

   if (objt_server(blah))
       do_something(objt_server(blah));

At -O2 the compiler manages to simplify the operation and see that the
second one returns the same result as the first one. But at -O1 that's
not always the case, and the compiler is able to emit a second
expression and sees the potential null that results from it, and may
warn about a potential null deref (e.g. with gcc-6.5). There are two
solutions to this:
  - either the result of the first test has to be passed to a local
    variable
  - or the second reference ought to be unchecked using the __objt_*
    variant.

This patch fixes all occurrences at once by taking the second approach
(the least intrusive). For constructs like:

   objt_server(blah) ? objt_server(blah)->name : "no name"

a macro could be useful. It would for example take the object type
(server), the field name (name) and the default value. But there
are probably not enough occurrences across the whole code for this
to really matter.

This should be backported wherever it applies.
2021-12-06 09:11:47 +01:00
Tim Duesterhus
caf5f5d302 BUG/MEDIUM: sample: Fix memory leak in sample_conv_jwt_member_query
The function leaked one full buffer per invocation. Fix this by simply removing
the call to alloc_trash_chunk(), the static chunk from get_trash_chunk() is
sufficient.

This bug was introduced in 0a72f5ee7c, which is
2.5-dev10. This fix needs to be backported to 2.5+.
2021-12-03 09:03:55 +01:00
Christopher Faulet
af93d2fd70 BUG/MINOR: resolvers: Don't overwrite the error for invalid query domain name
When a response is validated, the query domain name is checked to be sure it
is the same than the one requested. When an error is reported, the wrong
goto label was used. Thus, the error was lost. Instead of
RSLV_RESP_WRONG_NAME, RSLV_RESP_INVALID was reported.

This bug was introduced by the commit c1699f8c1 ("MEDIUM: resolvers: No
longer store query items in a list into the response").

This patch should fix the issue #1473. No backport is needed.
2021-12-02 10:05:04 +01:00
Christopher Faulet
02c893332b BUG/MEDIUM: h1: Properly reset h1m flags when headers parsing is restarted
If H1 headers are not fully received at once, the parsing is restarted a
last time when all headers are finally received. When this happens, the h1m
flags are sanitized to remove all value set during parsing.

But some flags where erroneously preserved. Among others, H1_MF_TE_CHUNKED
flag was not removed, what could lead to parsing error.

To fix the bug and make things easy, a mask has been added with all flags
that must be preserved. It will be more stable. This mask is used to
sanitize h1m flags.

This patch should fix the issue #1469. It must be backported to 2.5.
2021-12-02 09:46:29 +01:00
Emeric Brun
2ad2b1c94c BUG/MAJOR: segfault using multiple log forward sections.
For each new log forward section, the proxy was added to the log forward
proxy list but the ref on the previous log forward section's proxy was
scratched using "init_new_proxy" which performs a memset. After configuration
parsing this list contains only the last section's proxy.

The post processing walk through this list to resolve "ring" names.
Since some section's proxies are missing in this list, the resolving
is not done for those ones and the pointer on the ring is kept to null
causing a segfault at runtime trying to write a log message
into the ring.

This patch shift the "init_new_proxy" before adding the ref on the
previous log forward section's proxy on currently parsed one.

This patch shoud fix github issue #1464

This patch should be backported to 2.3
2021-12-01 15:21:56 +01:00
Christopher Faulet
c1699f8c1b MEDIUM: resolvers: No longer store query items in a list into the response
When the response is parsed, query items are stored in a list, attached to
the parsed response (resolve_response).

First, there is one and only one query sent at a time. Thus, there is no
reason to use a list. There is a test to be sure there is only one query
item in the response. Then, the reference on this query item is only used to
validate the domain name is the one requested. So the query list can be
removed. We only expect one query item, no reason to loop on query records.
In addition, the query domain name is now immediately checked against the
resolution domain name. This way, the query item is only manipulated during
the response parsing.
2021-12-01 15:21:56 +01:00
Christopher Faulet
80b2e34b18 BUG/MEDIUM: resolvers: Detach query item on response error
When a new response is parsed, it is unexpected to have an old query item
still attached to the resolution. And indeed, when the response is parsed
and validated, the query item is detached and used for a last check on its
dname. However, this is only true for a valid response. If an error is
detected, the query is not detached. This leads to undefined behavior (most
probably a crash) on the next response because the first element in the
query list is referencing an old response.

This patch must be backported as far as 2.0.
2021-12-01 11:47:08 +01:00
Christopher Faulet
4ab2679689 BUG/MINOR: server: Don't rely on last default-server to init server SSL context
During post-parsing stage, the SSL context of a server is initialized if SSL
is configured on the server or its default-server. It is required to be able
to enable SSL at runtime. However a regression was introduced, because the
last parsed default-server is used. But it is not necessarily the
default-server line used to configure the server. This may lead to
erroneously initialize the SSL context for a server without SSL parameter or
the skip it while it should be done.

The problem is the default-server used to configure a server is not saved
during configuration parsing. So, the information is lost during the
post-parsing. To fix the bug, the SRV_F_DEFSRV_USE_SSL flag is
introduced. It is used to know when a server was initialized with a
default-server using SSL.

For the record, the commit f63704488e ("MEDIUM: cli/ssl: configure ssl on
server at runtime") has introduced the bug.

This patch must be backported as far as 2.4.
2021-12-01 11:47:08 +01:00
Christopher Faulet
41951ab9d6 MINOR: mux-h1: add stat for total amount of bytes received and sent
Add counters for total amount of bytes received and sent. Bytes received and
sent via kernel splicing are also counted.
2021-12-01 11:47:08 +01:00
Christopher Faulet
3bca28c9fd MINOR: mux-h1: add stat for total count of connections/streams
Add counters for total number of http1 connections/stream since haproxy
startup. Contrary to open_conn/stream, they are never reset to zero.
2021-12-01 11:47:08 +01:00
Christopher Faulet
60fa051e71 MINOR: mux-h1: count open connections/streams on stats
Implement as a gauge h1 counters for currently open connections and
streams. The counters are decremented when closing the stream or the
connection.
2021-12-01 11:47:08 +01:00
Christopher Faulet
563c345f6f MINOR: mux-h1: add counters instance to h1c
Add pointer to counters as a member for h1c structure. This pointer is
initialized on h1_init function. This is useful to quickly access and
manipulate the counters inside every h1 functions.
2021-12-01 11:47:08 +01:00
Christopher Faulet
b4c584eed1 MINOR: mux-h1: register a stats module
Use statistics API to register a new stats module generating counters on h1
module. The counters are attached to frontend/backend instances.
2021-12-01 11:47:08 +01:00
Christopher Faulet
6580f2868e MINOR: mux-h1: Improve H1 traces by adding info about http parsers
Info about the request and the response parsers are now displayed in H1
traces for advanced and complete verbosity only. This should help debugging.

This patch may be backported as far as 2.4.
2021-12-01 11:47:08 +01:00
Christopher Faulet
f5ce320156 BUG/MINOR: mux-h1: Fix splicing for messages with unknown length
Splicing was disabled fo Messages with an unknown length (no C-L or T-E
header) with no valid reason. So now, it is possible to use the kernel
splicing for such messages.

This patch should be backported as far as 2.4.
2021-12-01 11:47:08 +01:00
Christopher Faulet
140f1a5852 BUG/MEDIUM: mux-h1: Fix splicing by properly detecting end of message
Since the 2.4.4, the splicing support in the H1 multiplexer is buggy because
end of the message is not properly detected.

On the 2.4, when the requests is spliced, there is no issue. But when the
response is spliced, the client connection is always closed at the end of the
message. Note the response is still fully sent.

On the 2.5 and higher, when the last requests on a connection is spliced, a
client abort is reported. For other requests there is no issue. In all cases,
the requests are fully sent. When the response is spliced, the server connection
hangs till the server timeout and a server abort is reported. The response is
fully sent with no delay.

The root cause is the EOM block suppression. There is no longer extra block to
be sure to call a last time rcv_buf()/snd_buf() callback functions. At the end,
to fix the issue, we must now detect end of the message in rcv_pipe() and
snd_pipe() callback functions. To do so, we rely on the announced message length
to know when the payload is finished. This works because the chunk-encoded
messages are not spliced.

This patch must be backported as far as 2.4 after an observation period.
2021-12-01 11:46:21 +01:00
David CARLIER
b1e190a885 MEDIUM: pool: Following up on previous pool trimming update.
Apple libmalloc has its own notion of memory arenas as malloc_zone with
rich API having various callbacks for various allocations strategies but
here we just use the defaults.
In trim_all_pools,  we advise to purge each zone as much as possible, called "greedy" mode.
2021-12-01 10:38:31 +01:00
Remi Tricot-Le Breton
bb3e80e181 BUG/MINOR: vars: Fix the set-var and unset-var converters
In commit 3a4bedccc6 the variable logic was changed. Instead of
accessing variables by their name during runtime, the variable tables
are now indexed by a hash of the name. But the set-var and unset-var
converters try to access the correct variable by calculating a hash on
the sample instead of the already calculated variable hash.

It should be backported to 2.5.
2021-12-01 10:32:19 +01:00
Frédéric Lécaille
008386bec4 MINOR: quic: Delete the ODCIDs asap
As soon as the connection ID (the one choosen by the QUIC server) has been used
by the client, we can delete its original destination connection ID from its tree.
2021-11-30 12:01:32 +01:00
Frédéric Lécaille
a7d2c09468 MINOR: quic: Enable the Key Update process
This patch modifies ha_quic_set_encryption_secrets() to store the
secrets received by the TLS stack and prepare the information for the
next key update thanks to quic_tls_key_update().
qc_pkt_decrypt() is modified to check if we must used the next or the
previous key phase information to decrypt a short packet.
The information are rotated if the packet could be decrypted with the
next key phase information. Then new secrets, keys and IVs are updated
calling quic_tls_key_update() to prepare the next key phase.
quic_build_packet_short_header() is also modified to handle the key phase
bit from the current key phase information.
2021-11-30 11:51:12 +01:00
Frédéric Lécaille
a7973a6dce MINOR: quic: Add quic_tls_key_update() function for Key Update
This function derives the next RX and TX keys and IVs from secrets
for the next key update key phase. We also implement quic_tls_rotate_keys()
which rotate the key update key phase information to be able to continue
to decrypt old key phase packets. Most of these information are pointers
to unsigned char.
2021-11-30 11:51:12 +01:00
Frédéric Lécaille
6e351d6c19 MINOR: quic: Optional header protection key for quic_tls_derive_keys()
quic_tls_derive_keys() is responsible to derive the AEAD keys, IVs and$
header protection key from a secret provided by the TLS stack. We want
to make the derivation of the header protection key be optional. This
is required for the Key Update process where there is no update for
the header protection key.
2021-11-30 11:51:12 +01:00
Frédéric Lécaille
40df78f116 MINOR: quic: Add structures to maintain key phase information
When running Key Update process, we must maintain much information
especially when the key phase bit has been toggled by the peer as
it is possible that it is due to late packets. This patch adds
quic_tls_kp new structure to do so. They are used to store
previous and next secrets, keys and IVs associated to the previous
and next RX key phase. We also need the next TX key phase information
to be able to encrypt packets for the next key phase.
2021-11-30 11:51:12 +01:00
Frédéric Lécaille
39484de813 MINOR: quic: Add a function to derive the key update secrets
This is the function used to derive an n+1th secret from the nth one as
described in RFC9001 par. 6.1.
2021-11-30 11:51:12 +01:00
Frédéric Lécaille
fc768ecc88 MINOR: quic: Dynamically allocate the secrete keys
This is done for any encryption level. This is to prepare the Key Update feature.
2021-11-30 11:51:12 +01:00
Frédéric Lécaille
d77c50b6d6 MINOR: quic: Possible crash when inspecting the xprt context
haproxy may crash when running this statement in qc_lstnr_pkt_rcv():
	conn_ctx = qc->conn->xprt_ctx;
because qc->conn may not be initialized. With this patch we ensure
qc->conn is correctly initialized before accessing its ->xprt_ctx
members. We zero the xrpt_ctx structure (ssl_conn_ctx struct), then
initialize its ->conn member with HA_ATOMIC_STORE. Then, ->conn and
->conn->xptr_ctx members of quic_conn struct can be accessed with HA_ATOMIC_LOAD()
2021-11-30 11:50:42 +01:00
Frédéric Lécaille
e2660e61e2 MINOR: quic: Rename qc_prep_hdshk_pkts() to qc_prep_pkts()
qc_prep_hdshk_pkts() does not prepare only handshake packets but
any type of packet.
2021-11-30 11:47:46 +01:00
Frédéric Lécaille
b5b5247b18 MINOR: quic: Immediately close if no transport parameters extension found
If the ClientHello callback does not manage to find a correct QUIC transport
parameters extension, we immediately close the connection with
missing_extension(109) as TLS alert which is turned into 0x16d QUIC connection
error.
2021-11-30 11:47:46 +01:00
Frédéric Lécaille
1fc5e16c4c MINOR: quic: More accurate immediately close.
When sending a CONNECTION_CLOSE frame to immediately close the connection,
do not provide CRYPTO data to the TLS stack. Do not built anything else than a
CONNECTION_CLOSE and do not derive any secret when in immediately close state.
Seize the opportunity of this patch to rename ->err quic_conn struct member
to ->error_code.
2021-11-30 11:47:46 +01:00
Frédéric Lécaille
067a82bba1 MINOR: quic: Set "no_application_protocol" alert
We set this TLS error when no application protocol could be negotiated
via the TLS callback concerned. It is converted as a QUIC CRYPTO_ERROR
error (0x178).
2021-11-30 11:47:46 +01:00
Willy Tarreau
3cc1e3d5ca BUILD: evports: remove a leftover from the dead_fd cleanup
Commit b1f29bc62 ("MINOR: activity/fd: remove the dead_fd counter") got
rid of FD_UPDT_DEAD, but evports managed to slip through the cracks and
wasn't cleaned up, thus it doesn't build anymore, as reported in github
issue #1467. We just need to remove the related lines since the situation
is already handled by the remaining conditions.

Thanks to Dominik Hassler for reporting the issue and confirming the fix.

This must be backported to 2.5 only.
2021-11-30 09:34:32 +01:00
Christopher Faulet
d98da3bc90 BUG/MEDIUM: cli: Properly set stream analyzers to process one command at a time
The proxy used by the master CLI is an internal proxy and no filter are
registered on it. Thus, there is no reason to take care to set or unset
filter analyzers in the master CLI analyzers. AN_REQ_FLT_END was set on the
request channel to prevent the infinite forward and be sure to be able to
process one commande at a time. However, the only work because
CF_FLT_ANALYZE flag was used by error as a channel analyzer instead of a
channel flag. This erroneously set AN_RES_FLT_END on the request channel,
that really prevent the infinite forward, be side effet.

In fact, We must avoid this kind of trick because this only work by chance
and may be source of bugs in future. Instead, we must always keep the CLI
request analyzer and add an early return if the response is not fully
processed. It happens when the CLI response analyzer is set.

This patch must be backported as far as 2.0.
2021-11-29 11:28:54 +01:00
Willy Tarreau
781f07a620 BUILD: pools: only detect link-time jemalloc on ELF platforms
The build broke on Windows and MacOS after commit ed232148a ("MEDIUM:
pool: refactor malloc_trim/glibc and jemalloc api addition detections."),
because the extern+attribute(weak) combination doesn't result in a really
weak symbol and it causes an undefined symbol at link time.

Let's reserve this detection to ELF platforms. The runtime detection using
dladdr() remains used if defined.

No backport needed, this is purely 2.6.
2021-11-26 16:13:17 +01:00
William Lallemand
efd954793e BUG/MINOR: mworker: deinit of thread poller was called when not initialized
Commit 67e371e ("BUG/MEDIUM: mworker: FD leak of the eventpoll in wait
mode") introduced a regression. Upon a reload it tries to deinit the
poller per thread, but no poll loop was initialized after loading the
configuration.

This patch fixes the issue by moving this part of the code in
mworker_reload(), since this function will be called only when the
poller is fully initialized.

This patch must be backported in 2.5.
2021-11-26 14:43:57 +01:00
David Carlier
d450ff636c MEDIUM: pool: support purging jemalloc arenas in trim_all_pools()
In the case of Linux/glibc, falling back to malloc_trim if jemalloc
had not been detected beforehand.
2021-11-25 18:54:50 +01:00
David Carlier
ed232148a7 MEDIUM: pool: refactor malloc_trim/glibc and jemalloc api addition detections.
Attempt to detect jemalloc at runtime before hand whether linked or via
symbols overrides, and fall back to malloc_trim/glibc for Linux otherwise.
2021-11-25 18:54:50 +01:00
Amaury Denoyelle
5bae85d0d2 MINOR: quic: use more verbose QUIC traces set at compile-time
Remove the verbosity set to 0 on quic_init_stdout_traces. This will
generate even more verbose traces on stdout with the default verbosity
of 1 when compiling with -DENABLE_QUIC_STDOUT_TRACES.
2021-11-25 18:10:58 +01:00
Amaury Denoyelle
118b2cbf84 MINOR: quic: activate QUIC traces at compilation
Implement a function quic_init_stdout_traces called at STG_INIT. If
ENABLE_QUIC_STDOUT_TRACES preprocessor define is set, the QUIC trace
module will be automatically activated to emit traces on stdout on the
developer level.

The main purpose for now is to be able to generate traces on the haproxy
docker image used for QUIC interop testing suite. This should facilitate
test failure analysis.
2021-11-25 16:12:44 +01:00
Amaury Denoyelle
7d3aea50b8 MINOR: qpack: support litteral field line with non-huff name
Support qpack header using a non-huffman encoded name in a litteral
field line with name reference.

This format is notably used by picoquic client and should improve
haproxy interop covering.
2021-11-25 11:41:29 +01:00
Amaury Denoyelle
d6a352a58b MEDIUM: quic: handle CIDs to rattach received packets to connection
Change the way the CIDs are organized to rattach received packets DCID
to QUIC connection. This is necessary to be able to handle multiple DCID
to one connection.

For this, the quic_connection_id structure has been extended. When
allocated, they are inserted in the receiver CID tree instead of the
quic_conn directly. When receiving a packet, the receiver tree is
inspected to retrieve the quic_connection_id. The quic_connection_id
contains now contains a reference to the QUIC connection.
2021-11-25 11:41:29 +01:00
Amaury Denoyelle
42b9f1c6dd CLEANUP: quic: add comments on CID code
Add minor comment to explain how the CID are stored in the QUIC
connection.
2021-11-25 11:33:35 +01:00
Amaury Denoyelle
aff4ec86eb REORG: quic: add comment on rare thread concurrence during CID alloc
The comment is here to warn about a possible thread concurrence issue
when treating INITIAL packets from the same client. The macro unlikely
is added to further highlight this scarce occurence.
2021-11-25 11:13:12 +01:00
Amaury Denoyelle
cb318a80e4 MINOR: quic: do not reject PADDING followed by other frames
It is valid for a QUIC packet to contain a PADDING frame followed by
one or several other frames.

quic_parse_padding_frame() does not require change as it detect properly
the end of the frame with the first non-null byte.

This allow to use quic-go implementation which uses a PADDING-CRYPTO as
the first handshake packet.
2021-11-25 11:13:12 +01:00
William Lallemand
67e371ea14 BUG/MEDIUM: mworker: FD leak of the eventpoll in wait mode
Since 2.5, before re-executing in wait mode, the master can have a
working configuration loaded, with a eventpoll fd. This case was not
handled correctly and a new eventpoll FD is leaking in the master at
each reload, which is inherited by the new worker.

Must be backported in 2.5.
2021-11-25 10:45:29 +01:00
William Lallemand
befab9ee4a BUG/MINOR: mworker: does not add the -sf in wait mode
Since the wait mode is automatically executed after charging the
configuration, -sf was shown in argv[] with the previous PID, which is
normal, but also the current one. This is only a visual problem when
listing the processes, because -sf does not do anything in wait mode.

Fix the issue by removing the whole "-sf" part in wait mode, but the
executed command can be seen in the argv[] of the latest worker forked.

Must be backported in 2.5.
2021-11-25 10:39:54 +01:00
Bertrand Jacquin
7fbc7708d4 BUG/MINOR: lua: remove loop initial declarations
HAProxy is documented to support gcc >= 3.4 as per INSTALL file, however
hlua.c makes use of c11 only loop initial declarations leading to build
failure when using gcc-4.9.4:

  x86_64-unknown-linux-gnu-gcc -Iinclude  -Wchar-subscripts -Wcomment -Wformat -Winit-self -Wmain -Wmissing-braces -Wno-pragmas -Wparentheses -Wreturn-type -Wsequence-point -Wstrict-aliasing -Wswitch -Wtrigraphs -Wuninitialized -Wunknown-pragmas -Wunused-label -Wunused-variable -Wunused-value -Wpointer-sign -Wimplicit -pthread -fdiagnostics-color=auto -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -O3 -msse -mfpmath=sse -march=core2 -g -fPIC -g -Wall -Wextra -Wundef -Wdeclaration-after-statement -fwrapv -Wno-unused-label -Wno-sign-compare -Wno-unused-parameter -Wno-clobbered -Wno-missing-field-initializers -Wtype-limits      -DUSE_EPOLL  -DUSE_NETFILTER   -DUSE_PCRE2 -DUSE_PCRE2_JIT -DUSE_POLL -DUSE_THREAD -DUSE_BACKTRACE   -DUSE_TPROXY -DUSE_LINUX_TPROXY -DUSE_LINUX_SPLICE -DUSE_LIBCRYPT -DUSE_CRYPT_H -DUSE_GETADDRINFO -DUSE_OPENSSL -DUSE_LUA -DUSE_ACCEPT4   -DUSE_SLZ -DUSE_CPU_AFFINITY -DUSE_TFO -DUSE_NS -DUSE_DL -DUSE_RT      -DUSE_PRCTL  -DUSE_THREAD_DUMP        -DUSE_PCRE2 -DPCRE2_CODE_UNIT_WIDTH=8  -I/usr/local/include -DCONFIG_HAPROXY_VERSION=\"2.5.0\" -DCONFIG_HAPROXY_DATE=\"2021/11/23\" -c -o src/connection.o src/connection.c
  src/hlua.c: In function 'hlua_config_prepend_path':
  src/hlua.c:11292:2: error: 'for' loop initial declarations are only allowed in C99 or C11 mode
    for (size_t i = 0; i < 2; i++) {
    ^
  src/hlua.c:11292:2: note: use option -std=c99, -std=gnu99, -std=c11 or -std=gnu11 to compile your code

This commit moves loop iterator to an explicit declaration.

Must be backported to 2.5 because this issue was introduced in
v2.5-dev10~69 with commit 9e5e586e35 ("BUG/MINOR: lua: Fix lua error
 handling in `hlua_config_prepend_path()`")
2021-11-25 09:07:34 +01:00