Commit Graph

13949 Commits

Author SHA1 Message Date
Amaury Denoyelle
b5454d42df MINOR: h3: do not wait a complete frame for demuxing
Previously, H3 demuxer refused to proceed the payload if the frame was
not entirely received and the QCS buffer is not full. This code was
duplicated from the H2 demuxer.

In H2, this is a justified optimization as only one frame at a time can
be demuxed. However, this is not the case in H3 with interleaved frames
in the lower layer QUIC STREAM frames.

This condition is now removed. H3 demuxer will proceed payload as soon
as possible. An exception is kept for HEADERS frame as the code is not
able to deal with partial HEADERS.

With this change, H3 demuxer should consume less memory. To ensure that
we never received a HEADER bigger than the RX buffer, we should use the
H3 SETTINGS_MAX_FIELD_SECTION_SIZE.
2022-05-18 15:31:46 +02:00
Amaury Denoyelle
ca21c768b9 MINOR: ncbuf: refactor ncb_advance()
First adjusted some typos in comments inside the function. Second,
change the naming of some variable to reduce confusion.

A special case has been inserted when advance is done inside a GAP block
and this block is the last of the buffer. In this case, the whole buffer
will be emptied, equivalent to a ncb_init() operation.
2022-05-18 15:30:13 +02:00
Amaury Denoyelle
f6dbdc1444 BUG/MINOR: ncbuf: fix ncb_is_empty()
ncb_is_empty() was plainly incorrect as it directly dereferences the
memory to read offset blocks instead of ncb_read_off(). The result is
undefined.

Also, BUG_ON() statement is wrong when the buffer starts with a data
block. In this case, ncb_head() is not the first gap offset but instead
just random data. The calculated sum in BUG_ON() statement has thus no
meaning and may cause an abort. Adjust this by reorganizing the whole
function. Only the first data block size is read. If and only if not
nul, the first gap size is then checked.

ncb_is_full() has been rewritten to share the same model as
ncb_is_empty().
2022-05-18 15:23:29 +02:00
Amaury Denoyelle
80d0572a31 BUG/MEDIUM: quic: fix Rx buffering
The quic-conn manages a buffer to store received QUIC packets. When the
buffer wraps, the gap is filled until the end with junk and packets can
be inserted at the start of the buffer.

On the other end, deletion is implemented via quic_rx_pkts_del().
Packets are removed one by one if their refcount is nul. If junk is
found, the buffer is emptied until its wrap.

This seems to work in most cases but a bug was found in a particular
case : on insertion if buffer gap is not at the end of the buffer. In
this case, the gap was filled, which is useless as now the buffer is
full and the packet cannot be inserted. Worst, on deletion, when junk is
removed there is a risk to removed new packets. This can happens in the
following case :
1. buffer contig space is too small, junk is inserted in the middle of
   it
2. on quic_rx_pkts_del() invocation, a packet is removed, but not the
   next one because its refcount is still positive. When a new packet is
   received, it will be stored after the junk.
3. on next quic_rx_pkts_del(), when junk is removed, all contig data is
   cleared, with newer packets data too.

This will cause a transfer between a client and haproxy to be stalled.
This can be reproduced with big enough POST requests. I triggered it
with ngtcp2 and 10M of posted data.

Hopefully, the solution of this bug is simple. If contig space is not
big enough to store a packet, but the space is not at the end of the
buffer, no junk is inserted and the packet is dropped as we cannot
buffered it. This ensures that junk is only present at the end of the
buffer and when removed no packets data is purged with it.
2022-05-18 15:02:14 +02:00
Christopher Faulet
f229e1894c CLEANUP: httpclient: Remove useless test on ss_dst in httpclient_applet_init()
In httpclient_applet_init() function, ss_dst variable is always defined
before the call to sockaddr_alloc(). There is no reason to test it.

This patch should fix the issue #1706.
2022-05-18 09:29:33 +02:00
Christopher Faulet
9e3c8d5512 CLEANUP: peers: Remove unreachable code in peer_session_create()
An error label is now unreachable in peer_session_create().

This patch should fix the issue #1704.
2022-05-18 09:04:53 +02:00
Christopher Faulet
fa463afa8f BUG/MINOR: spoe: Fix error handling in spoe_init_appctx()
labels used in goto statement was not called in the right order. Thus if
there is an error during the appctx startup, it is possible to leak a task.

This patch should fix the issue #1703. No backport needed.
2022-05-18 09:04:53 +02:00
Tim Duesterhus
7ad27d41b4 CLEANUP: http_ana: Make use of the return value of stream_generate_unique_id()
Even if `unique_id` and `s->unique_id` are identical it is a bit odd to
`isttest()` `unique_id` and then use `s->unique_id` in the call to `http_add_header()`.

This "issue" was introduced in a17e66289c,
because before that commit the function returned the length of the ID, as it
was not an ist.
2022-05-18 07:19:01 +02:00
Remi Tricot-Le Breton
ccc0355c41 MINOR: ssl: Add 'ssl-provider-path' global option
When loading providers with 'ssl-provider' global options, this
ssl-provider-path option can be used to set the search path that is to
be used by openssl. It behaves the same way as the OPENSSL_MODULES
environment variable.
2022-05-17 18:09:17 +02:00
Christopher Faulet
bc684acae7 CLEANUP: proxy: Remove dead code when parsing "http-restrict-req-hdr-names" option
negation or default modifiers are not supported for this option. However,
this was already tested earlier in cfg_parse_listen() function. Thus, when
"http-restrict-req-hdr-names" option is parsed, the keyword modifier is
always equal to KWM_STD. It is useless to test it again at this place.

This patch should solve the issue #1702.
2022-05-17 16:13:22 +02:00
Christopher Faulet
2d9cc85b74 MINOR: conn-stream/applet: Stop setting appctx as the endpoint context
The appctx is already the endpoint target. It is confusing to also use it to
set the endpoint context. So, never set the endpoint ctx when an appctx is
created or attached to an existing conn-stream.
2022-05-17 16:13:22 +02:00
Maciej Zdeb
34e4085f8a MEDIUM: peers: Balance applets across threads
When creating a new applet for peer outgoing connection, we check
the load on each thread. Threads with least applet count are
preferred.

With this solution we avoid a situation when many outgoing
connections run on the same thread causing significant load on
single CPU core.
2022-05-17 16:13:22 +02:00
Maciej Zdeb
d01be2ab13 MINOR: peers: Track number of applets run by thread
Maintain number of peers applets run on all threads. It will be used
in next patch for least loaded thread selection.
2022-05-17 16:13:22 +02:00
Christopher Faulet
d9c1d33fa1 MEDIUM: applet: Add support for async appctx startup on a thread subset
It is now possible to start an appctx on a thread subset. Some controls were
added here and there. It is forbidden to start a backend appctx on another
thread than the local one. If a frontend appctx is started on another thread
or a thread subset, the applet .init callback function must be defined. This
callback function is responsible to finalize the appctx startup. It can be
performed synchornously. In this case, the appctx is started on the local
thread. It is not really useful but it is valid. Or it can be performed
asynchronously. In this case, .init callback function is called when the
appctx is woken up for the first time. When this happens, the appctx
affinity is set to the current thread to be able to start the session and
the stream.
2022-05-17 16:13:22 +02:00
Christopher Faulet
6095d57701 MINOR: applet: Add API to start applet on a thread subset
In the same way than for the tasks, the applets api was changed to be able
to start a new appctx on a thread subset. For now the feature is
disabled. Only appctx_new_here() is working. But it will be possible to
start an appctx on a specific thread or a subset via a mask.
2022-05-17 16:13:22 +02:00
Christopher Faulet
6712dc680c MEDIUM: peers: Refactor peer appctx creation
A .init callback function is defined for the peer_applet applet. This
function finishes the appctx startup by calling appctx_finalize_startup()
and its handles the stream customization.
2022-05-17 16:13:22 +02:00
Christopher Faulet
387e79727c MINOR: peers: Add a ref to peers section in the peer structure
This change is required to handle asynchrone init of the appctx. It is now
possible to directly get the peers section associated to a peer.
2022-05-17 16:13:22 +02:00
Christopher Faulet
aee57fc277 MEDIUM: sink: Refactor sink forwarder appctx creation
A .init callback function is defined for the sink_forward_applet applet.
This function finishes the appctx startup by calling
appctx_finalize_startup() and its handles the stream customization.
2022-05-17 16:13:22 +02:00
Christopher Faulet
2ae25ea24b MINOR: sink: Add a ref to sink in the sink_forward_target structure
This change is required to be able to refactor the init stage of appctx. It
is now possible to directly get the sink from a forward target.
2022-05-17 16:13:22 +02:00
Christopher Faulet
b1e0836ecf MEDIUM: httpclient: Refactor http-client appctx creation
A .init callback function is defined for the httpclient_applet applet. This
function finishes the appctx startup by calling appctx_finalize_startup()
and its handles the stream customization.
2022-05-17 16:13:22 +02:00
Christopher Faulet
5f35a3e2ec MEDIUM: lua: Refactor cosocket appctx creation
A .init callback function is defined for the update_applet applet. This
function finishes the appctx startup by calling appctx_finalize_startup()
and its handles the stream customization.
2022-05-17 16:13:22 +02:00
Christopher Faulet
69ebc3093a MEDIUM: spoe: Refactor SPOE appctx creation
A .init callback function is defined for the spoe_applet applet. This
function finishes the spoe_appctx initialization. It also finishes the
appctx startup by calling appctx_finalize_startup() and its handles the
stream customization.
2022-05-17 16:13:22 +02:00
Christopher Faulet
9223851a80 MEDIUM: dns: Refactor dns appctx creation
A .init callback function is defined for the dns_session_applet applet. This
function finishes the appctx startup by calling appctx_finalize_startup()
and its handles the stream customization.
2022-05-17 16:13:21 +02:00
Christopher Faulet
d0c4ec04b8 MINOR: applet: Add function to release appctx on error during init stage
appctx_free_on_early_error() must be used to release a freshly created
frontend appctx if an error occurred during the init stage. It takes care to
release the stream instead of the appctx if it exists. For a backend appctx,
it just calls appctx_free().
2022-05-17 16:13:21 +02:00
Christopher Faulet
8718c95c0a MINOR: applet: Add a function to finalize frontend appctx startup
appctx_finalize_startup() may be used to finalize the frontend appctx
startup. It is responsible to create the appctx's session and the frontend
conn-stream. On error, it is the caller responsibility to release the
appctx. However, the session is released if it was created. On success, if
an error is encountered in the caller function, the stream must be released
instead of the appctx.

This function should ease the init stage when new appctx is created.
2022-05-17 16:13:21 +02:00
Christopher Faulet
16c0d9cda0 MINOR: applet: Add appctx_init() helper fnuction
It is just a helper function that call the .init applet callback function,
if it exists. This will simplify a bit the init stage when a new applet is
started. For now, this callback function is only used when a new service is
started.
2022-05-17 16:13:21 +02:00
Christopher Faulet
ab5d1dceed MINOR: stream: Export stream_free()
The stream_free() function is now public. It is mandatory to properly handle
errors when a new applet is started.
2022-05-17 16:13:21 +02:00
Christopher Faulet
c9929380a4 MINOR: applet: Change return value for .init callback function
0 is now returned on success and -1 on error.
2022-05-17 16:13:21 +02:00
Christopher Faulet
92202da2da MINOR: applet: Let the frontend appctx release the session
The session created for frontend applets is now totally owns by the
corresponding appctx. It means the appctx is now responsible to release
it. This removes the hack in stream_free() about frontend applets to be sure
to release the session.
2022-05-17 16:13:21 +02:00
Christopher Faulet
ac57bb527a MINOR: applet: Prepare appctx to own the session on frontend side
Applets were moved at the same level than multiplexers. Thus, gradually,
applets code is changed to be less dependent from the stream. With this
commit, the frontend appctx are ready to own the session. It means a
frontend appctx will be responsible to release the session.
2022-05-17 16:13:21 +02:00
Remi Tricot-Le Breton
9bf3a1f67e BUG/MINOR: ssl: Fix crash when no private key is found in pem
If no private key can be found in a bind line's certificate and
ssl-load-extra-files is set to none we end up trying to call
X509_check_private_key with a NULL key, which crashes.

This fix should be backported to all stable branches.
2022-05-17 15:51:41 +02:00
David Carlier
7198c700bc MINOR: tools: add get_exec_path implementation for solaris based systems.
We can use getexecname() which fetches AT_SUN_EXECNAME from the auxiliary
vectors.
2022-05-17 11:44:21 +02:00
Tim Duesterhus
9b6becb312 CLEANUP: Remove unused function hlua_get_top_error_string
This function has no prototype defined in a header and is not used in hlua.c
either, thus it can be safely removed. Found with -Wmissing-prototypes.
2022-05-17 11:40:33 +02:00
Tim Duesterhus
6eded62f6a CLEANUP: Add missing header to hlua_fcn.c
Found with -Wmissing-prototypes:

    src/hlua_fcn.c:53:5: fatal error: no previous prototype for function 'hlua_checkboolean' [-Wmissing-prototypes]
    int hlua_checkboolean(lua_State *L, int index)
        ^
    src/hlua_fcn.c:53:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
    int hlua_checkboolean(lua_State *L, int index)
    ^
    static
    1 error generated.
2022-05-17 11:40:33 +02:00
Tim Duesterhus
2a0688aa89 CLEANUP: Add missing header to ssl_utils.c
Found with -Wmissing-prototypes:

    src/ssl_utils.c:22:5: fatal error: no previous prototype for function 'cert_get_pkey_algo' [-Wmissing-prototypes]
    int cert_get_pkey_algo(X509 *crt, struct buffer *out)
        ^
    src/ssl_utils.c:22:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
    int cert_get_pkey_algo(X509 *crt, struct buffer *out)
    ^
    static
    1 error generated.
2022-05-17 11:40:33 +02:00
Remi Tricot-Le Breton
1746a388c5 MINOR: ssl: Add 'ssl-provider' global option
When HAProxy is linked to an OpenSSLv3 library, this option can be used
to load a provider during init. You can specify multiple ssl-provider
options, which will be loaded in the order they appear. This does not
prevent OpenSSL from parsing its own configuration file in which some
other providers might be specified.
A linked list of the providers loaded from the configuration file is
kept so that all those providers can be unloaded during cleanup. The
providers loaded directly by OpenSSL will be freed by OpenSSL.
2022-05-17 10:56:05 +02:00
Remi Tricot-Le Breton
e80976526c MINOR: ssl: Add 'ssl-propquery' global option
This option can be used to define a default property query used when
fetching algorithms in OpenSSL providers. It follows the format
described in https://www.openssl.org/docs/man3.0/man7/property.html.
It is only available when haproxy is built with SSL support and linked
to OpenSSLv3 libraries.
2022-05-17 10:56:05 +02:00
Remi Tricot-Le Breton
5194446b76 MEDIUM: ssl: Delay random generator initialization after config parsing
The random generator initialization needs to be performed before the
chroot but it is not needed before. If we want to add provider
configuration option to the configuration file, they need to be
processed before any call to a crypto-related OpenSSL function.
We can then delay the initialization until after the configuration file
is parsed and processed.
2022-05-17 10:55:59 +02:00
Christopher Faulet
18c13d3bd8 MEDIUM: http-ana: Add a proxy option to restrict chars in request header names
The "http-restrict-req-hdr-names" option can now be set to restrict allowed
characters in the request header names to the "[a-zA-Z0-9-]" charset.

Idea of this option is to not send header names with non-alphanumeric or
hyphen character. It is especially important for FastCGI application because
all those characters are converted to underscore. For instance,
"X-Forwarded-For" and "X_Forwarded_For" are both converted to
"HTTP_X_FORWARDED_FOR". So, header names can be mixed up by FastCGI
applications. And some HAProxy rules may be bypassed by mangling header
names. In addition, some non-HTTP compliant servers may incorrectly handle
requests when header names contain characters ouside the "[a-zA-Z0-9-]"
charset.

When this option is set, the policy must be specify:

  * preserve: It disables the filtering. It is the default mode for HTTP
              proxies with no FastCGI application configured.

  * delete: It removes request headers with a name containing a character
            outside the "[a-zA-Z0-9-]" charset. It is the default mode for
            HTTP backends with a configured FastCGI application.

  * reject: It rejects the request with a 403-Forbidden response if it
            contains a header name with a character outside the
            "[a-zA-Z0-9-]" charset.

The option is evaluated per-proxy and after http-request rules evaluation.

This patch may be backported to avoid any secuirty issue with FastCGI
application (so as far as 2.2).
2022-05-16 16:00:26 +02:00
Amaury Denoyelle
f46393ac44 MINOR: ncbuf: fix warnings for testing build
Using -Wall reveals several warning when building ncbuf testing API. One
of them was about the signedness mismatch. The other one was with an
incorrect print format.
2022-05-16 11:32:33 +02:00
Amaury Denoyelle
48fbad45e2 BUG/MEDIUM: ncbuf: fix null buffer usage
ncbuf public API functions were not ready to deal with a NCBUF_NULL as
parameter. Strenghten these functions by handling it properly.

Most of the functions will consider the buffer as empty and silently
returns. The only exception is ncb_init(buf) which cannot be called
with a NCBUF_NULL. This seems legitimate to consider this as a bug and
not silently failed in this case.
2022-05-16 11:28:41 +02:00
Amaury Denoyelle
45fce8fcb5 CLEANUP: quic: remove unused quic_rx_strm_frm
quic_rx_strm_frm type was used to buffered STREAM frames received out of
order. Now the MUX is able to deal directly with these frames and
buffered it inside its ncbuf.
2022-05-13 17:29:52 +02:00
Amaury Denoyelle
00f87bbaa3 CLEANUP: mux-quic: remove unused fields for Rx
Rx has been simplified since the conversion of buffer to a ncbuf. The
old buffer can now be removed. The frms tree is also removed. It was
used previously to stored out-of-order received STREAM frames. Now the
MUX is able to buffer them directly into the ncbuf.
2022-05-13 17:29:52 +02:00
Amaury Denoyelle
3db98e9d13 MEDIUM: mux-quic/h3/qpack: use ncbuf for uni streams
This commit is the equivalent for uni-streams of previous commit
  MEDIUM: mux-quic/h3/hq-interop: use ncbuf for bidir streams

All unidirectional streams data is now handle in MUX Rx ncbuf. The
obsolete buffer is not unused and will be cleared in the following
patches.
2022-05-13 17:29:49 +02:00
Amaury Denoyelle
1290f1ebfb MEDIUM: mux-quic/h3/hq-interop: use ncbuf for bidir streams
Add a ncbuf for data reception on qcs. Thanks to this, the MUX is able
to buffered all received frame directly into the buffer. Flow control
parameters will be used to ensure there is never an overflow.

This change will simplify Rx path with the future deletion of acked
frames tree previously used for frames out of order.
2022-05-13 17:28:46 +02:00
Amaury Denoyelle
b5ca943ff9 BUG/MINOR: ncbuf: fix coverity warning on uninit sz_data
Coverity reports that data block generated by ncb_blk_first() has
sz_data field uninitialized. This has no real impact as it has no sense
for data block. Set to 0 to hide the warning.

This should fix github issue #1695.
2022-05-13 17:06:24 +02:00
Willy Tarreau
26f221bd55 MINOR: config: make sure never to mix dgram and stream protocols on a bind line
It is absolutely not possible to use the same "bind" line to listen to
both quic and tcp for example, because no single transport layer would
fit both modes and we'll need the type to choose one then to choose a
mux. Let's make sure this does not happen. This may be relaxed in the
future if we manage to instantiate transport layers on the fly, but the
SSL vs quic part might be tricky to handle.
2022-05-13 17:00:09 +02:00
Willy Tarreau
8d31ab0438 MINOR: tools: improve error message accuracy in str2sa_range
The error message when mixing stream and dgram protocols in an
address speaks about sockets while it ought to speak about addresses,
let's fix this as in some contexts it can be a bit confusing.
2022-05-13 16:50:00 +02:00
Willy Tarreau
df94313e0e BUG/MEDIUM: mux-quic: fix a thinko in the latest cs/endpoint cleanup
Fred & Amaury found that I messed up with qc_detach() in commit 4201ab791
("CLEANUP: muxes: make mux->attach/detach take a conn_stream endpoint"),
causing a segv in this case with endp->cs == NULL being passed to
__cs_mux(). It obviously ought to have been endp->target like in other
muxes.

No backport needed.
2022-05-13 16:34:40 +02:00
Willy Tarreau
973cf90714 MINOR: ext-check: indicate the transport and protocol of a server
Valerio Pachera explained [1] that external checks would benefit from
having a variable indicating if SSL is being used or not on the server
being checked, and the discussion derived to also indicating the protocol
in use.

This patch adds two environment variables for external checks:
  - HAPROXY_SERVER_SSL: equals "0" when SSL is not used, "1" when it is
  - HAPROXY_SERVER_PROTO: contains one of the following words to describe
    the protocol used with this server:
      - "cli": the haproxy CLI. Normally not seen
      - "syslog": this is a syslog TCP server
      - "peers": this is a peers TCP server
      - "h1": this is an HTTP/1.x server
      - "h2": this is an HTTP/2 server
      - "tcp": this is any other TCP server

The patch is very simple, and may be backported to recent versions if
needed. This closes github issue #1692.

[1] https://www.mail-archive.com/haproxy@formilux.org/msg42233.html
2022-05-13 16:06:29 +02:00
Willy Tarreau
6796a06278 CLEANUP: conn_stream: merge cs_new_from_{mux,applet} into cs_new_from_endp()
The two functions became exact copies since there's no more special case
for the appctx owner. Let's merge them into a single one, that simplifies
the code.
2022-05-13 14:28:48 +02:00
Willy Tarreau
0698c80a58 CLEANUP: applet: remove the unneeded appctx->owner
This one is the pointer to the conn_stream which is always in the
endpoint that is always present in the appctx, thus it's not needed.
This patch removes it and replaces it with appctx_cs() instead. A
few occurences that were using __cs_strm(appctx->owner) were moved
directly to appctx_strm() which does the equivalent.
2022-05-13 14:28:48 +02:00
Willy Tarreau
1c3ead45a4 MINOR: applet: replace cs_applet_shut() with appctx_shut()
The former takes a conn_stream still attached to a valid appctx,
which also complicates the termination of the applet. Instead, let's
pass the appctx which already points to the endpoint, this allows us
to properly detach the conn_stream before the call, which is cleaner
and safer.
2022-05-13 14:28:48 +02:00
Willy Tarreau
4201ab791d CLEANUP: muxes: make mux->attach/detach take a conn_stream endpoint
The mux ->detach() function currently takes a conn_stream. This causes
an awkward situation where the caller cs_detach_endp() has to partially
mark it as released but not completely so that ->detach() finds its
endpoint and context, and it cannot be done later since it's possible
that ->detach() deletes the endpoint. As such the endpoint link between
the conn_stream and the mux's stream is in a transient situation while
we'd like it to be clean so that the mux's ->detach() code can call any
regular function it wants that knows the regular semantics of the
relation between the CS and the endpoint.

A better approach consists in slightly modifying the detach() API to
better match the reality, which is that the endpoint is detached but
still alive and that it's the only part the function is interested in.

As such, this patch modifies the function to take an endpoint there,
and by analogy (or simplicity) does the same for ->attach(), even
though it looks less important there since we're always attaching an
endpoint to a conn_stream anyway. It is possible that in the future
the API could evolve to use more endpoints that provide a bit more
flexibility in the API, but at this point we don't need to go further.
2022-05-13 14:28:48 +02:00
Willy Tarreau
cfbfc3f091 MINOR: mux-pt: remove the now unneeded conn_stream from the context
Since we always have a valid endpoint we can safely use it to access
the conn_stream and stop using ctx->cs. That's one less pointer to
care about.
2022-05-13 14:28:48 +02:00
Willy Tarreau
01c2a4a86f MINOR: mux-quic: remove the now unneeded conn_stream from the qcs
Since we always have a valid endpoint we can safely use it to access
the conn_stream and stop using qcs->cs. That's one less pointer to
care about.
2022-05-13 14:28:48 +02:00
Willy Tarreau
b57669e6a4 MINOR: mux-fcgi: remove the now unneeded conn_stream from the fcgi_strm
Since we always have a valid endpoint we can safely use it to access
the conn_stream and stop using fstrm->cs. That's one less pointer to
care about.
2022-05-13 14:28:48 +02:00
Willy Tarreau
c84610c2ac MINOR: mux-fcgi: make sure any stream always has an endpoint
The principle that each mux stream should have an endpoint is not
guaranteed for closed streams that map to the dummy static streams.
Let's have a dummy endpoint for use with such streams. It only has
the DETACHED flag and a NULL conn_stream, and is referenced by all
the closed streams so that we can afford not to test strm->endp when
trying to access the flags or the CS.
2022-05-13 14:28:48 +02:00
Willy Tarreau
cd6bb1a5e5 MINOR: mux-h2: remove the now unneeded conn_stream from the h2s
Since we always have a valid endpoint we can safely use it to access
the conn_stream and stop using h2s->cs. That's one less pointer to
care about.
2022-05-13 14:28:48 +02:00
Willy Tarreau
b22b5f02af MINOR: mux-h2: make sure any h2s always has an endpoint
The principle that each mux stream should have an endpoint is not
guaranteed for closed streams that map to the dummy static streams.
Let's have a dummy endpoint for use with such streams. It only has
the DETACHED flag and a NULL conn_stream, and is referenced by all
the closed streams so that we can afford not to test h2s->endp when
trying to access the flags or the CS.
2022-05-13 14:28:48 +02:00
Willy Tarreau
56d5a819d7 MINOR: mux-h1: remove the now unneeded h1s->cs
There is always an endpoint link in a stream, and this endpoint link
contains a pointer to the conn_stream it's attached to, so the one in
the h1 stream is always duplicate now. Let's always use endp->cs
instead and get rid of it.
2022-05-13 14:28:48 +02:00
Willy Tarreau
efb4618c6e MINOR: conn_stream: add a pointer back to the cs from the endpoint
Muxes and applets need to have both a pointer to the endpoint and to the
conn_stream. It would seem more natural that they only have a pointer to
the endpoint (that is always there) and that this one has an optional
pointer to the conn_stream. This would reduce the number of elements to
manipulate in lower level code. In addition, the conn_stream is not much
used from the lower layers (wake and exceptional events mostly).
2022-05-13 14:28:48 +02:00
Willy Tarreau
66435e5f63 CLEANUP: applet: use the appctx's endp instead of cs->endp
The few applets that set CS_EP_EOI or CS_EP_ERROR used to set it on the
endpoint retrieved from the conn_stream while it's already available on
the appctx itself. Better use the appctx one to limit the unneeded
interactions between the two sides.
2022-05-13 14:28:46 +02:00
Willy Tarreau
15b0721ca5 CLEANUP: mux-quic: always take the endp from the qcs not the cs
At a few places the endpoint pointer was retrieved from the conn_stream
while it's safer and more long-term proof to take it from the qcs. Let's
just do that.
2022-05-13 14:27:57 +02:00
Willy Tarreau
7d299c284b CLEANUP: mux-fcgi: always take the endp from the fstrm not the cs
At a few places the endpoint pointer was retrieved from the conn_stream
while it's safer and more long-term proof to take it from the fstrm.
Let's just do that.
2022-05-13 14:27:57 +02:00
Willy Tarreau
7a2705f921 CLEANUP: mux-pt: always take the endp from the context not the cs
At a few places the endpoint pointer was retrieved from the conn_stream
while it's safer and more long-term proof to take it from the context.
Let's just do that.
2022-05-13 14:27:57 +02:00
Willy Tarreau
aff21f9a96 CLEANUP: mux-h2: always take the endp from the h2s not the cs
At a few places the endpoint pointer was retrieved from the conn_stream
while it's safer and more long-term proof to take it from the h2s. Let's
just do that.
2022-05-13 14:27:57 +02:00
Willy Tarreau
61533d3486 CLEANUP: mux-h1: always take the endp from the h1s not the cs
At a few places the endpoint pointer was retrieved from the conn_stream
while it's safer and more long-term proof to take it from the h1s. Let's
just do that.
2022-05-13 14:27:57 +02:00
Willy Tarreau
386346f5eb MINOR: conn_stream: make cs_set_error() work on the endpoint instead
Wherever we need to report an error, we have an even easier access to
the endpoint than the conn_stream. Let's first adjust the API to use
the endpoint and rename the function accordingly to cs_ep_set_error().
2022-05-13 14:27:57 +02:00
Christopher Faulet
b112b1d02a CLEANUP: mux-h1: Fix comments and error messages for global options
Wrong name was used in comments and error messages for
"h1-header-case-adjust" and "h1-headers-case-adjust-file" global options.
2022-05-13 12:04:24 +02:00
Christopher Faulet
0f9c0f5801 MINOR: mux-h1: Add global option accpet payload for any HTTP/1.0 requests
Since the 2.5, for security reason, HTTP/1.0 GET/HEAD/DELETE requests with a
payload are rejected (See e136bd12a "MEDIUM: mux-h1: Reject HTTP/1.0
GET/HEAD/DELETE requests with a payload" for details). However it may be an
issue for old clients.

To avoid any compatibility issue with such clients,
"h1-accept-payload-with-any-method" global option was added. It must only be
set if there is a good reason to do so because it may lead to a request
smuggling attack on some servers or intermediaries.

This patch should solve the issue #1691. it may be backported to 2.5.
2022-05-13 12:04:24 +02:00
William Lallemand
ae053b30da BUG/MEDIUM: wdt: don't trigger the watchdog when p is unitialized
In wdt_handler(), does not try to trigger the watchdog if the
prev_cpu_time wasn't initialized.

This prevents an unexpected trigger of the watchdog when it wasn't
initialized yet. This case could happen in the master just after loading
the configuration. This would show a trace where the <diff> value is equal
to the <now> value in the trace, and the <poll> value would be 0.

For example:

    Thread 1 is about to kill the process.
    *>Thread 1 : id=0x0 act=1 glob=1 wq=0 rq=0 tl=0 tlsz=0 rqsz=0
                  stuck=1 prof=0 harmless=0 wantrdv=0
                  cpu_ns: poll=0 now=6005541706 diff=6005541706
                  curr_task=0

Thanks to Christian Ruppert for repporting the problem.

Could be backported in every stable versions.
2022-05-13 11:28:08 +02:00
Boyang Li
e0c5435d76 BUG/MEDIUM: lua: fix argument handling in data removal functions
Lua API Channel.remove() and HTTPMessage.remove() expects 1 to 3
arguments (counting the manipulated object), with offset and length
being the 2nd and 3rd argument, respectively.

hlua_{channel,http_msg}_del_data() incorrectly gets the 3rd argument as
offset, and 4th (nonexistent) as length. hlua_http_msg_del_data() also
improperly checks arguments. This patch fixes argument handling in both.

Must be backported to 2.5.
2022-05-13 08:40:03 +02:00
Amaury Denoyelle
eeeeed44ea MINOR: ncbuf: write unit tests
Implement a series of unit test to validate ncbuf. This is written with
a main function which can be compiled independently using the following
command-line :
 $ gcc -DSTANDALONE -lasan -I./include -o ncbuf src/ncbuf.c

The first part tests is used to test ncb_add()/ncb_advance(). After each
call a loop is done on the buffer blocks which should ensure that the
gap infos are correct.

The second part generates random offsets and insert them until the
buffer is full. The buffer is then resetted and all random offsets are
re-inserted in the reverse order : the buffer should be full once again.

The generated binary takes arguments to change the tests execution.
 "usage: ncbuf [-r] [-s bufsize] [-h bufhead] [-p <delay_msec>]"
2022-05-12 18:29:55 +02:00
Amaury Denoyelle
df25acf47f MINOR: ncbuf: implement advance
A new function ncb_advance() is implemented. This is used to advance the
buffer head pointer. This will consume the front data while forming a
new gap at the end for future data.

On success NCB_RET_OK is returned. The operation can be rejected if a
too small new gap is formed in front of the buffer.
2022-05-12 18:29:55 +02:00
Amaury Denoyelle
b830f0d8d9 MINOR: ncbuf: define various insertion modes
Define three different ways to proceed insertion. This configures how
overlapping data is treated.
- NCB_ADD_PRESERVE : in this mode, old data are kept during insertion.
- NCB_ADD_OVERWRT : new data will overwrite old ones.
- NCB_ADD_COMPARE : this mode adds a new test in check stage. The
  overlapping old and new data must be identical or else the insertion
  is not conducted. An error NCB_RET_DATA_REJ is used in this case.

The mode is specified with a new argument to ncb_add() function.
2022-05-12 18:27:05 +02:00
Amaury Denoyelle
077e096b30 MINOR: ncbuf: implement insertion
Implement a new function ncb_add() to insert data in ncbuf. This
operation is conducted in two stages. First, a simulation will be run to
ensure that insertion can be proceeded. If a gap is formed, either
before or after the new data, it must be big enough to store its header,
or else the insertion is aborted.

After this check stage, the insertion is conducted block by block with
the function pair ncb_fill_data_blk()/ncb_fill_gap_blk().

A new type ncb_ret is used as a return value. For the moment, only
success or gap-size error is used. It is planned to add new error types
in the future when insertion will be extended.
2022-05-12 18:27:05 +02:00
Amaury Denoyelle
edeb0a61a2 MINOR: ncbuf: optimize storage for the last gap
Relax the constraint for gap storage when this is the last block.
ncb_blk API functions will consider that if a gap is stored near the end
of the buffer, without the space to store its header, the gap will cover
entirely the buffer end.

For these special cases, the gap size/data size are not write/read
inside the gap to prevent an overflow. Such a gap is designed in
functions as "reduced gap" and will be flagged with the value
NCB_BK_F_FIN.

This should reduce the rejection on future add operation when receiving
data in-order. Without reduced gap handling, an insertion would be
rejected if it covers only partially the last buffer bytes, which can be
a very common case.
2022-05-12 18:18:47 +02:00
Amaury Denoyelle
d5d2ed90f0 MINOR: ncbuf: complete API and define block interal abstraction
Implement two new functions to report the total data stored accross the
whole buffer and the data stored at a specific offset until the next gap
or the buffer end.

To facilitate implementation of these new functions and also future
add/delete operations, a new abstraction is introduced : ncb_blk. This
structure represents a block of either data or gap in the buffer. It
simplifies operation when moving forward in the buffer. The first buffer
block can be retrieved via ncb_blk_first(buf). The block at a specific
offset is accessed via ncb_blk_find(buf, off).

This abstraction is purely used in functions but not stored in the ncbuf
structure per-se. This is necessary to keep the minimal memory
footprint.
2022-05-12 18:18:47 +02:00
Amaury Denoyelle
1b5f77fc18 MINOR: ncbuf: define non-contiguous buffer
Define the new type ncbuf. It can be used as a buffer with
non-contiguous data and wrapping support.

To reduce as much as possible the memory footprint, size of data and
gaps are stored in the gaps themselves. This put some limitation on the
buffer usage. A reserved space is present just before the head to store
the size of the first data block. Also, add and delete operations will
be constrained to ensure minimal gap sizes are preserved.

The sizes stored in the gaps are represented by a custom type named
ncb_sz_t. This type is a typedef to easily change it : this has a
direct impact on the maximum buffer size (MAX(ncb_sz_t) - sizeof(ncb_sz_t))
and the minimal gap sizes (sizeof(ncb_sz_t) * 2)).
Currently, it is set to uint32_t.
2022-05-12 18:13:21 +02:00
Frédéric Lécaille
4ba3b4ef67 CLEANUP: quic: Useless use of pointer for quic_hkdf_extract()
There is no need to use a pointer to the output buffer length.
2022-05-12 17:48:35 +02:00
Frédéric Lécaille
a54e49d0b1 CLEANUP: quic: wrong use of eb*entry() macro
This wrong use has no consequence because the ->node member fields of
eb*node structs are the first.
2022-05-12 17:48:35 +02:00
Frédéric Lécaille
36b28ed012 MINOR: quic: Short packets always embed a trailing AEAD TAG
We must drop as soon as possible too small 1-RTT packets to be valid QUIC
packets to avoid replying with stateless reset packets.
2022-05-12 17:48:35 +02:00
Frédéric Lécaille
e2fb1bf487 MINOR: quic: Send stateless reset tokens
Add send_stateless_reset() to send a stateless reset packet. It prepares
a packet to build a 1-RTT packet with quic_stateless_reset_token_cpy()
to copy a stateless reset token derived from the cluster secret with
the destination connection ID received as salt.
Also add QUIC_EV_STATELESS_RST new trace event to at least to have a trace
of the connection which are reset.
2022-05-12 17:48:35 +02:00
Frédéric Lécaille
806e6cf392 MINOR: quic: Stateless reset token copy to transport parameters
A server may send the stateless reset token associated to the current
connection from its transport parameters. So, let's copy it from
qc_lstnt_params_init().
2022-05-12 17:48:35 +02:00
Frédéric Lécaille
395a64dd81 MINOR: qc_new_conn() rework for stateless reset
The stateless reset token of a connection is generated from qc_new_conn() when
allocating the first connection ID. A QUIC server can copy it into its transport
parameters to allow the peer to reset the associated connection.
This latter is not easily reachable after having returned from qc_new_conn().
We want to be able to initialize the transport parameters from this function which
has an access to all the information to do so.

Extract the code used to initialize the transport parameters from qc_lstnr_pkt_rcv()
and make it callable from qc_new_conn(). qc_lstnr_params_init() is implemented
to accomplish this task for a haproxy listener.
Modify qc_new_conn() to reduce its the number of parameters.
The source address coming from Initial packets is also copied from qc_new_conn().
2022-05-12 17:48:35 +02:00
Frédéric Lécaille
28a1795515 MINOR: quic: Initialize stateless reset tokens with HKDF secrets
Add quic_stateless_reset_token_init() wrapper function around
quic_hkdf_extract_and_expand() function to derive the stateless reset tokens
attached to the connection IDs from "cluster-secret" configuration setting
and call it each time we instantiate a QUIC connection ID.
2022-05-12 17:48:35 +02:00
Frédéric Lécaille
0226c521b0 MINOR: quic: new_quic_cid() code moving
This function will have to call another one from quic_tls.[ch] soon.
As we do not want to include quic_tls.h from xprt_quic.h because
quic_tls.h already includes xprt_quic.h, let's moving it into
xprt_quic.c.
2022-05-12 17:48:35 +02:00
Frédéric Lécaille
7b92c81e43 MINOR: quic-tls: Add quic_hkdf_extract_and_expand() for HKDF
This is a wrapper function around OpenSSL HKDF API functions to
use the "extract-then-expand" HKDF mode as defined by rfc5869.
This function will be used to derived stateless reset tokens
from secrets ("cluster-secret" conf. keyword) and CIDs (as salts).
2022-05-12 17:48:35 +02:00
Frédéric Lécaille
372508cc42 MINOR: config: Add "cluster-secret" new global keyword
It could be usefull to set a ASCII secret which could be used for different
usages. For instance, it will be used to derive QUIC stateless reset tokens.
2022-05-12 17:48:35 +02:00
Frédéric Lécaille
7cc8b3166a MINOR: quic: Add correct ack delay values to ACK frames
A ->time_received new member is added to quic_rx_packet to store the time the
packet are received. ->largest_time_received is added the the packet number
space structure to store this timestamp for the packet with a new largest
packet number to be acknowledged. QUIC_FL_PKTNS_NEW_LARGEST_PN new flag is
added to mark a packet number space as having to acknowledged a packet wih a
new largest packet number. In this case, the packet number space ack delay
must be recalculated.
Add quic_compute_ack_delay_us() function to compute the ack delay from the value
of the time a packet was received. Used only when a packet with a new largest
packet number.
2022-05-12 15:30:14 +02:00
Frédéric Lécaille
8726d633d4 MINOR: quic: Add a debug counter for sendto() errors
As we do not have any task to be wake up by the poller after sendto() error,
we add an sendto() error counter to the quic_conn struct.
Dump its values from qc_send_ppkts().
2022-05-12 15:11:53 +02:00
Willy Tarreau
e872f75fc4 MINOR: mux-h2: report a trace event when failing to create a new stream
There are two reasons we can reject the creation of an h2 stream on the
frontend:
  - its creation would violate the MAX_CONCURRENT_STREAMS setting
  - there's no more memory available

And on the backend it's almost the same except that the setting might
have be negotiated after trying to set up the stream.

Let's add traces for such a sitaution so that it's possible to know why
the stream was rejected (currently we only know it was rejected).

It could be nice to backport this to the most recent versions.
2022-05-12 09:29:58 +02:00
Willy Tarreau
198b50770d BUG/MINOR: mux-h2: mark the stream as open before processing it not after
When a client doesn't respect the h2 MAX_CONCURRENT_STREAMS setting, we
rightfully send RST_STREAM to it so that the client closes. But the
max_id is only updated on the successful path of h2c_handle_stream_new(),
which may be reentered for partial frames or CONTINUATION frames, and as
a result we don't increment it if an extraneous stream ID is rejected.

Normally it doesn't have any consequence. But on a POST it can have some
if the DATA frame immediately follows the faulty HEADERS frame: with
max_id not incremented, the stream remains in IDLE state, and the DATA
frame now lands in an invalid state from a protocol's perspective, which
must lead to a connection error instead of a stream error.

This can be tested by modifying the code to send an arbitrarily large
MAX_CONCURRENT_STREAM setting and using h2load to send more concurrent
streams than configured: with a GET, only a tiny fraction of them will
report an error (e.g. 101 streams for 100 accepted will result in ~1%
failure), but when sending data, most of the streams will be reported
as failed because the connection will be closed. By updating the max_id
earlier, the stream is now considered as closed when the DATA frame
arrives and it's silently discarded.

This must be backported to all versions but only if the code is exactly
the same. Under no circumstance this ID may be updated for a partial frame
(i.e. only update it before or just after calling h2c_frt_steam_new()).
2022-05-12 09:29:58 +02:00
Emeric Brun
314e6ec822 BUG/MAJOR: dns: multi-thread concurrency issue on UDP socket
This patch adds a lock on the struct dgram_conn to ensure
that an other thread cannot trash a fd or alter its status
while the current thread processing it on for send/receive/connect
operations.

Starting with the 2.4 version this could cause a crash when a DNS
request is failing, setting the FD of the dgram structure to -1. If the
dgram structure is reused after that, a read access to fdtab[-1] is
attempted. The crash was only triggered when compiled with ASAN.

In previous versions the concurrency issue also exists but is less
likely to crash.

This patch must be backported until v2.4 and should be
adapt for v < 2.4.
2022-05-11 15:20:10 +02:00
Willy Tarreau
63fc900ba2 BUG/MEDIUM: ssl: fix the gcc-12 broken fix :-(
... or how a bogus warning forces you to do tricky changes in your code
and fail on a length test condition! Fortunately it changed in the right
direction that immediately broke, due to a missing "> sizeof(path)" that
had to be added to the already ugly condition.

This fixes recent commit 393e42ae5 ("BUILD: ssl: work around bogus warning
in gcc 12's -Wformat-truncation"). It may have to be backported if that
one is backported.
2022-05-09 21:16:13 +02:00
Willy Tarreau
d86793479f BUILD: listener: shut report of possible null-deref in listener_accept()
When building without threads, gcc 12 says that there's a null-deref in
_HA_ATOMIC_INC() called from listener_accept(). It's just that the code
was originally written in an attempt not to always have a proxy for a
listener and that there are two places where the pointer is tested before
being used, so the compiler concludes that the pointer might be null
hence that other places are null-derefs.

In practice the pointer cannot be null there (and never has been), but
since that code was initially built that way and it's only a matter of
adding a pair of braces to shut it up, let's respect that initial
attempt in case one day we need it.

This one was also reported by Ilya in issue #1513, though with threads
enabled in his case.

This may have to be backported if users complain about new breakage with
gcc-12.
2022-05-09 20:49:36 +02:00
Willy Tarreau
393e42ae5f BUILD: ssl: work around bogus warning in gcc 12's -Wformat-truncation
As was first reported by Ilya in issue #1513, Gcc 12 incorrectly reports
a possible overflow from the concatenation of two strings whose size was
previously checked to fit:

  src/ssl_crtlist.c: In function 'crtlist_parse_file':
  src/ssl_crtlist.c:545:58: error: '%s' directive output may be truncated writing up to 4095 bytes into a region of size between 1 and 4096 [-Werror=format-truncation=]
    545 |                         snprintf(path, sizeof(path), "%s/%s",  global_ssl.crt_base, crt_path);
        |                                                          ^~
  src/ssl_crtlist.c:545:25: note: 'snprintf' output between 2 and 8192 bytes into a destination of size 4097
    545 |                         snprintf(path, sizeof(path), "%s/%s",  global_ssl.crt_base, crt_path);
        |                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

It would be a bit concerning to disable -Wformat-truncation because it
might detect real programming mistakes at other places. The solution
adopted in this patch is absolutely ugly and error-prone, but it works,
it consists in integrating the snprintf() call in the error condition
and to test the result again. Let's hope a smarter compiler will not
warn that this test is absurd since guaranteed by the first condition...

This may have to be backported for those suffering from a compiler upgrade.
2022-05-09 20:32:11 +02:00
Remi Tricot-Le Breton
444d702130 BUG/MINOR: ssl: Fix typos in crl-file related CLI commands
The CRL file CLI update code was strongly based off the CA one and some
copy-paste issues were then introduced.

This patch fixes GitHub issue #1685.
It should be backported to 2.5.
2022-05-09 14:23:04 +02:00
William Lallemand
589570df1f MEDIUM: ssl: ignore dotfiles when loading a dir w/ crt
Ignore the files starting with a dot when trying to load a directory
with the "crt" directive.

Should fix issue #1689.
2022-05-09 10:41:51 +02:00
William Lallemand
e4b93eb947 MINOR: ssl: ignore dotfiles when loading a dir w/ ca-file
Ignore the files starting with a dot when trying to load a directory
with the "ca-file directive".
2022-05-09 09:33:25 +02:00
Willy Tarreau
6ef1648dc2 CLEANUP: stats: rename the stats state values an mark the old ones deprecated
The STAT_ST_* values have been abused by virtually every applet and CLI
keyword handler, and this must not continue as it's a source of bugs and
of overly complicated code.

This patch renames the states to STAT_STATE_*, and keeps the previous
enum while marking each entry as deprecated. This should be sufficient to
catch out-of-tree code that might rely on them and to let them know what
to do with that.
2022-05-06 18:33:49 +02:00
Willy Tarreau
1c0715b12a CLEANUP: cli: move the status print context into its own context
Now that the CLI's print context is alone in the appctx, it's possible
to refine the appctx's ctx layout so that the cli part matches exactly
a regular svcctx, and as such move the CLI context into an svcctx like
other applets. External code will still build and work because the
struct cli perfectly maps onto the struct cli_print_ctx that's located
into svc.storage. This is of course only to make a smooth transition
during 2.6 and will disappear immediately after.

A tiny change had to be applied to the opentracing addon which performs
direct accesses to the CLI's err pointer in its own print function. The
rest uses the standard cli_print_* which were the only ones that needed
a small change.

The whole "ctx.cli" struct could be tagged as deprecated so that any
possibly existing external code that relies on it will get build
warnings, and the comments in the struct are pretty clear about the
way to fix it, and the lack of future of this old API.
2022-05-06 18:33:22 +02:00
Willy Tarreau
aa229ccc4c MINOR: lua: move the http service context out of appctx.ctx
Just like for the TCP service, let's move the context away from
appctx.ctx. A new struct hlua_http_ctx was defined, reserved in
hlua_applet_http_init() and used everywhere else. Similarly, the
task dump code will no more report decoded stack traces in case
these services would be involved. That may be solved later.
2022-05-06 18:13:36 +02:00
Willy Tarreau
e23f33bbfe MINOR: lua: move the tcp service storage outside of appctx.ctx
The use-service mechanism for Lua in TCP mode relies on the
hlua_tcp storage in appctx->ctx. We can move its definition to
hlua.c and simply use appctx_reserve_svcctx() to reserve and access
the stoage. One tiny side effect is that the task dump used in panics
will not show anymore the Lua call stack in its trace. For this a
better API is needed from the Lua code to expose a function that does
the job from an appctx.
2022-05-06 18:13:36 +02:00
Willy Tarreau
5321da9df0 MEDIUM: lua: move the cosocket storage outside of appctx.ctx
The Lua cosockets were using appctx.ctx.hlua_cosocket. Let's move this
to a local definition of "hlua_csk_ctx" in hlua.c, which is allocated
from the appctx by hlua_socket_new(). There's a notable change which is
that, while previously the xref link with the peer was established with
the appctx, it's now in the hlua_csk_ctx. This one must then hold a
pointer to the appctx. The code was adjusted accordingly, and now that
part of the code doesn't use the appctx.ctx anymore.
2022-05-06 18:13:36 +02:00
Willy Tarreau
f61494c708 CLEANUP: cache: take the context out of appctx.ctx
The context was moved to a local definition in the cache code, and
there's nothing specific to the cache anymore in the appctx. The
struct is stored into the appctx's storage area via the svcctx.
2022-05-06 18:13:36 +02:00
Willy Tarreau
c7afedc140 BUILD: applet: mark the appctx's st2 variable as deprecated
This one has been misused for a while as well, it's time to deprecate it
since we don't use it anymore. It will be removed in 2.7 and for now is
only marked as deprecated. Since we need to guarantee that it's zeroed
before starting any applet or CLI command, it was moved into an anonymous
union where its sibling is not marked as deprecated so that we can
continue to initialize it without triggering a warning.

If you found this commit after a bisect session you initiated to figure
why you got some build warnings and don't know what to do, have a look
at the code that deals with the "show fd", "show sess" or "show servers"
commands, as it's supposed to be self-explanatory about the tiny changes
to apply to your code to port it. If you find APPLET_MAX_SVCCTX to be
too small for your use case, either kindly ask for a tiny extension
(and try to get your code merged), or just use a pool.
2022-05-06 18:13:36 +02:00
Willy Tarreau
23a2407843 CLEANUP: spoe: do not use appctx.ctx anymore
The spoe code already uses its own generic pointer, let's move it to
svcctx instead of keeping a struct spoe in the appctx union.
2022-05-06 18:13:36 +02:00
Willy Tarreau
455caef642 CLEANUP: peers: do not use appctx.ctx anymore
The peers code already uses its own generic pointer, let's move it to
svcctx instead of keeping a struct peers in the appctx union.
2022-05-06 18:13:36 +02:00
Willy Tarreau
1eea6657fb CLEANUP: httpclient: do not use the appctx.ctx anymore
The httpclient already uses its own pointer and only used to store this
single pointer into the appctx.ctx field. Let's just move it to the
svcctx and remove this entry from the appctx union.
2022-05-06 18:13:36 +02:00
Willy Tarreau
89a7c41e24 CLEANUP: httpclient/cli: use a locally-defined context instead of ctx.cli
The httpclient's CLI uses ctx.cli.i0 for its flags and .p0 for the client
instance. Let's have a locally defined structure for this so that we don't
need the generic cli variables anymore.
2022-05-06 18:13:36 +02:00
Willy Tarreau
b128f49d89 CLEANUP: cli: make "show cli sockets" use its own context
Let's create a show_sock_ctx to store the bind_conf and the listener.
The entry is reserved when entering the I/O handler since there's no
parser here. That's fine because the function doesn't touch the area.
2022-05-06 18:13:36 +02:00
Willy Tarreau
4df54eb151 CLEANUP: cli: simplify the "show cli sockets" I/O handler
The code is was a bit convoluted by the use of a state machine around
st2 that is not used since only the STAT_ST_LIST state was used, and
the test of global.cli_fe inside the loop while it ought better be
tested before entering there. Let's get rid of this unneded state and
simplify the code. There's no more need for ->st2 now. The code looks
more changed than it really is due to the reindent caused by the
removal of the switch statement, but "git show -b" shows what really
changed.
2022-05-06 18:13:36 +02:00
Willy Tarreau
307dbb33bb CLEANUP: cli: make "show env" use its own context
There is the variable to start from (or environ) and an option to stop
after dumping the first one, just like "show fd". Let's have a small
locally-defined context with these two fields.
2022-05-06 18:13:36 +02:00
Willy Tarreau
741a5a9cb4 CLEANUP: cli: make "show fd" use its own context
The "show fd" command used to rely on cli.i0 for the fd, and st2 just
to decide whether to stop after the first value or not. It could have
been possible to decide to use just a negative integer to dump a single
value, but it's as easy and more durable to declare a two-field struct
show_fd_ctx for this.
2022-05-06 18:13:36 +02:00
Willy Tarreau
acf6a44908 CLEANUP: proxy/cli: make "show backend" only use the generic context
Let's use appctx->svcctx instead of abusing cli.p0 to store the
current proxy being dumped.
2022-05-06 18:13:36 +02:00
Willy Tarreau
d741e9c4b1 CLEANUP: proxy/cli: get rid of appctx->st2 in "show servers"
Now that we have the show_srv_ctx, let's store a state in it. We only
need two states here, header and list.
2022-05-06 18:13:36 +02:00
Willy Tarreau
72a04238d5 CLEANUP: proxy/cli: make use of a locally defined context for "show servers"
The command uses a pointer to the current proxy being dumped, one to the
current server being dumped, an optional ID of the only proxy to dump
(which is in fact used as a boolean), and a flag indicating if we're
doing a "show servers conn" or a "show servers state". Let's move all
this to a struct show_srv_ctx.
2022-05-06 18:13:36 +02:00
Willy Tarreau
c6dfef7a0b CLEANUP: cache/cli: make use of a locally defined context for "show cache"
The command uses a pointer to a cache instance and the next key to dump,
they were in cli.p0/i0 respectively, let's move them to a struct
show_cache_ctx.
2022-05-06 18:13:36 +02:00
Willy Tarreau
12d5228a44 CLEANUP: resolvers/cli: remove the unneeded appctx->st2 from "show resolvers"
The command uses this state but _INIT immediately turns to _LIST, which
turns to _FIN at the end without doing anything in that state, thus the
only existing state is _LIST so we don't need to store a state. Let's
just get rid of it.
2022-05-06 18:13:36 +02:00
Willy Tarreau
db933d6fdd CLEANUP: resolvers/cli: make "show resolvers" use a locally-defined context
The command was using cli.p0/p1/p2 to select which section to dump, the
current section and the current ns. Let's instead have a locally defined
"show_resolvers_ctx" section for this.
2022-05-06 18:13:36 +02:00
Willy Tarreau
6e3fc483f7 CLEANUP: ring/cli: use a locally-defined context instead of using ctx.cli
The ring code was using ctx.cli.i0/p0/o0 to store its context during CLI
dumps via "show events" or "show errors". Let's use a locally defined
context and drop that.
2022-05-06 18:13:36 +02:00
Willy Tarreau
cba8838e59 CLEANUP: ring: pass the ring watch flags to ring_attach_cli(), not in ctx.cli
The ring watch flags (wait, seek end) were dangerously passed via ctx.cli.i0
from "show buf" in sink.c:cli_parse_show_events(), or implicitly reset in
"show errors". That's very unconvenient, difficult to follow, and prone to
short-term breakage.

Let's pass an extra argument to ring_attach_cli() to take these flags, now
defined in ring-t.h as RING_WF_*, and let the function set them itself
where appropriate (still ctx.cli.i0 for now).
2022-05-06 18:13:36 +02:00
Willy Tarreau
40e952f1a6 CLEANUP: debug/cli: make "debug dev memstats" not use ctx.cli anymore
There was only the need for a start and a stop pointer, and a show_all
flag. All of that moved to a locally-defined struct dev_mem_ctx.
2022-05-06 18:13:36 +02:00
Willy Tarreau
e06bbf3f19 CLEANUP: debug/cli: make "debug dev fd" not use ctx.cli anymore
The command only requires to store an int, but it will be useful later
to have a struct to pass extra info such as an "all" flag to dump all
FDs. The new context is now a struct dev_fd_ctx stored in svcctx.
2022-05-06 18:13:36 +02:00
Willy Tarreau
e8d006a79a CLEANUP: activity/cli: make "show profiling" not use ctx.cli anymore
The I/O handler was using ctx.cli.i0/i1/o0/o1. Let's put all that into
a locally-defined context and use it instead.
2022-05-06 18:13:36 +02:00
Willy Tarreau
42cc831abf CLEANUP: sink: use the generic context to store the forwarder's context
Instead of having a struct that contains a single pointer in the appctx
context, let's directly use the generic context pointer and get rid of
the now unused sft.ptr entry.
2022-05-06 18:13:36 +02:00
Willy Tarreau
0d626a5610 CLEANUP: dns: stop abusing the sink forwarder's context
The DNS code was abusing the sink forwarder's context as its own. Let's
make it directly use the generic context pointer instead.
2022-05-06 18:13:36 +02:00
Willy Tarreau
fa11df5d03 CLEANUP: ssl/cli: make "add ssl crtlist" not use st2 anymore
Several steps are used during the addition of a crtlist to yield during
long operations, and states are used for this. Let's just not use the
st2 anymore and place the state inside the add_crtlist_ctx struct instead.
2022-05-06 18:13:36 +02:00
Willy Tarreau
6b6c363a6b CLEANUP: ssl/cli: make "add ssl crtlist" use its own context
This command was using cli.p0/p1/p2 in the io_handler. Let's move them
to a command-specific "struct add_crtlist_ctx".
2022-05-06 18:13:36 +02:00
Willy Tarreau
a2fcca0939 CLEANUP: ssl/cli: make "{show|dump} ssl crtlist" use its own context
These commands were using cli.i0/p0/p1 and in a not very clean way since
they use the same parser but with different types depending on the I/O
handler. Given there was no explanation about what the variables were
supposed to be, they were named based on best guess and placed into a
new "show_crtlist_ctx" structure.
2022-05-06 18:13:36 +02:00
Willy Tarreau
170b35bb95 CLEANUP: ssl/cli: make "show ssl ocsp-response" not use cli.p0 anymore
Instead the single-pointer context is placed into appctx->svcctx.
There's no need to declare a structure there for this.
2022-05-06 18:13:36 +02:00
Willy Tarreau
9c5a38c1b8 CLEANUP: ssl/cli: make "show tlskeys" not use appctx->st2 anymore
A new "state" enum was added to "show_keys_ctx" for this, and only 3
states are needed.
2022-05-06 18:13:36 +02:00
Willy Tarreau
bd33864373 CLEANUP: ssl/cli: add a new "dump_entries" field to "show_keys_ref"
This gets rid of a ugly hack consisting in checking the IO handler's
address while one is defined as an inline function calling the second.
2022-05-06 18:13:36 +02:00
Willy Tarreau
a938052113 CLEANUP: ssl/cli: stop using ctx.cli.i0/i1/p0 for "show tls-keys"
This creates a local context of type show_keys_ctx which contains
the equivalent fields with more natural names.
2022-05-06 18:13:36 +02:00
Willy Tarreau
1d6dd80d05 CLEANUP: ssl/cli: stop using appctx->st2 for "commit ssl ca/crl"
A new entry "state" was added into the commit_cacrl_ctx struct instead.
2022-05-06 18:13:36 +02:00
Willy Tarreau
dec23dc43f CLEANUP: ssl/cli: use a local context for "commit ssl {ca|crl}file"
These two commands use distinct parse/release functions but a common
iohandler, thus they need to keep the same context. It was created
under the name "commit_cacrlfile_ctx" and holds a large part of the
pointers (6) and the ca_type field that helps distinguish between
the two commands for the I/O handler. It looks like some of these
fields could have been merged since apparently the CA part only
uses *cafile* and the CRL part *crlfile*, while both old and new
are of type cafile_entry and set only for each type. This could
probably even simplify some parts of the code that tries to use
the correct field.

These fields were the last ones to be migrated thus the appctx's
ssl context could finally be removed.
2022-05-06 18:13:36 +02:00
Willy Tarreau
a06b9a5ccf CLEANUP: ssl/cli: use a local context for "set ssl crlfile"
Just like for "set ssl cafile", the command doesn't really need this
context which doesn't outlive the parsing function but it was there
for a purpose so it's maintained. Only 3 fields were used from the
appctx's ssl context: old_crlfile_entry, new_crlfile_entry, and path.
These ones were reinstantiated into a new "set_crlfile_ctx" struct.
It could have been merged with the one used in "set cafile" if the
fields had been renamed since cafile and crlfile are of the same
type (probably one of them ought to be renamed?).

None of these fields could be dropped as they are still shared with
other commands.
2022-05-06 18:13:36 +02:00
Willy Tarreau
a37693f7d8 CLEANUP: ssl/cli: use a local context for "set ssl cafile"
Just like for "set ssl cert", the command doesn't really need this
context which doesn't outlive the parsing function but it was there
for a purpose so it's maintained. Only 3 fields were used from the
appctx's ssl context: old_cafile_entry, new_cafile_entry, and path.
These ones were reinstantiated into a new "set_cafile_ctx" struct.
None of them could be dropped as they are still shared with other
commands.
2022-05-06 18:13:36 +02:00
Willy Tarreau
329f4b4f2f CLEANUP: ssl/cli: use a local context for "set ssl cert"
The command doesn't really need any storage since there's only a parser,
but since it used this context, there might have been plans for extension,
so better continue with a persistent one. Only old_ckchs, new_ckchs, and
path were being used from the appctx's ssl context. There ones moved to
the local definition, and the two former ones were removed from the appctx
since not used anymore.
2022-05-06 18:13:36 +02:00
Willy Tarreau
cb1b4ed7b6 CLEANUP: ssl/cli: stop using appctx->st2 for "commit ssl cert"
A new entry "state" was added into the commit_cert_ctx struct instead.
2022-05-06 18:13:36 +02:00
Willy Tarreau
a645b6a21f CLEANUP: ssl/cli: use a local context for "commit ssl cert"
This command only really uses old_ckchs, new_ckchs and next_ckchi
from the appctx's ssl context. The new structure "commit_cert_ctx"
only has these 3 fields, though none could be removed from the shared
ssl context since they're still used by other commands.
2022-05-06 18:13:36 +02:00
Willy Tarreau
96c9a6c752 CLEANUP: ssl/cli: use a local context for "show ssl cert"
This command only really uses old_ckchs, cur_ckchs and the index
in which the transaction was stored. The new structure "show_cert_ctx"
only has these 3 fields, and the now unused "cur_ckchs" and "index"
could be removed from the shared ssl context.
2022-05-06 18:13:36 +02:00
Willy Tarreau
f3e8b3e877 CLEANUP: ssl/cli: use a local context for "show crlfile"
Now this command doesn't share any context anymore with "show cafile"
nor with the other commands. The previous "cur_cafile_entry" field from
the applet's ssl context was removed as not used anymore. Everything was
moved to show_crlfile_ctx which only has 3 fields.
2022-05-06 18:13:36 +02:00
Willy Tarreau
50c2f1e0cd CLEANUP: ssl/cli: use a local context for "show cafile"
Saying that the layout and usage of the various variables in the ssl
applet context is a mess would be an understatement. It's very hard
to know what command uses what fields, even after having moved away
from the mix of cli and ssl.

Let's extract the parts used by "show cafile" into their own structure.
Only the "show_all" field would be removed from the ssl ctx, the other
fields are still shared with other commands.
2022-05-06 18:13:35 +02:00
Willy Tarreau
bcda5f6bcd CLEANUP: hlua/cli: take the hlua_cli context definition out of the appctx
This context is used by CLI keywords registered by Lua. We can take
it out of the appctx and use the generic command context allocation so
that the appctx doesn't have to declare a specific one anymore. The
context is created during parsing.
2022-05-06 18:13:35 +02:00
Willy Tarreau
41f885241e CLEANUP: stats/cli: stop using appctx->st2
Instead, let's have the state as an enum inside the context. It's much
cleaner and safer as we know nobody else touches it.
2022-05-06 18:13:35 +02:00
Willy Tarreau
91cefcaba4 CLEANUP: stats/cli: take the "show stat" context definition out of the appctx
This makes use of the generic command context allocation so that the
appctx doesn't have to declare a specific one anymore. The context is
created during parsing (both in the CLI and HTTP).

The change looks large but it's particularly mechanical. The context
initialization appears in stats.c and http_ana.c. The context is used
in stats.c and resolvers.c since "show stat resolvers" points there.
That's the reason why the definition moved to stats.h. "show info"
and "show stat" continue to share the same state definition for now.

Nothing else was modified.
2022-05-06 18:13:35 +02:00
Willy Tarreau
7bf20caacc CLEANUP: cli: initialize the whole appctx->ctx, not just the stats part
Historically the CLI was a second access to the stats and we've continued
to initialize only the stats part when initializing the CLI. Let's make
sure we do that on the whole ctx instead. It's probably not more needed
at all nowadays but better stay on the safe side.
2022-05-06 18:13:35 +02:00
Willy Tarreau
ce9123c005 CLEANUP: peers/cli: remove unneeded state STATE_INIT
All the settings in this initial state are konwn at parsing time,
there's no need for an initial state to bootstrap other ones.
2022-05-06 18:13:35 +02:00
Willy Tarreau
3a31e37518 CLEANUP: peers/cli: stop using appctx->st2 for the dump state
Let's instead define a 4-state enum solely for this use case, and place
it into the command's context. Note that END and FIN were already
aliases, which is why they were merged.
2022-05-06 18:13:35 +02:00
Willy Tarreau
cb8bf17900 CLEANUP: peers/cli: take the "show peers" context definition out of the appctx
This makes use of the generic command context allocation so that the
appctx doesn't have to declare a specific one anymore. The context is
created during parsing. The code also uses st2 which deserves being
addressed in separate commit.
2022-05-06 18:13:35 +02:00
Willy Tarreau
c7e9706e0f CLEANUP: map/cli: always detach the backref from the list after "show map"
There's no point checking the state before deciding to detach the backref
on "show map", it should always be done if the list is not empty. Note
that being empty guarantees that it's not linked into the list, and
conversely not being empty guarantees that it's in the list, hence the
test doesn't need to be performed under the lock.
2022-05-06 18:13:35 +02:00
Willy Tarreau
a0d6280af4 CLEANUP: map/cli: stop using appctx->st2 for the dump state
Let's instead define a 3-state enum solely for this use case, and place
it into the command's context.
2022-05-06 18:13:35 +02:00
Willy Tarreau
76f771e78e CLEANUP: map/cli: stop using cli.i0/i1 to store the generation numbers
The "show map"/"clear map" code used to rely on the cli's i0/i1 fields
to store the generation numbers to work with. That's particularly dirty
because it's done at places where ctx.map is also manipulated while they
are part of the same union, and the reason why this didn't cause trouble
is because cli.i0/i1 are at offset 216/224 while the map parts end at
204, so luckily there was no overlap.

Let's add these fields to the map context.
2022-05-06 18:13:35 +02:00
Willy Tarreau
0fcecc63c8 CLEANUP: map/cli: take the "show map" context definition out of the appctx
This makes use of the generic command context allocation so that the
appctx doesn't have to declare a specific one anymore. The context is
created during parsing. Many commands, including pure parsers, use this
context but that's not a problem as it's designed to be used this way.
Due to this, many lines are changed but that's in fact a replacement of
"appctx->ctx.map" with "ctx->". Note that the code also uses st2 which
deserves being addressed in separate commit.
2022-05-06 18:13:35 +02:00
Willy Tarreau
0f154ed1ef CLEANUP: stick-table/cli: remove the unneeded STATE_INIT for "show table"
This state is pointless now, it just serves to initialize the initial
table pointer while this can be done more easily in the parser, so let's
do that and drop that state.
2022-05-06 18:13:35 +02:00
Willy Tarreau
7849d4c912 CLEANUP: stick-table/cli: stop using appctx->st2 for the dump state
Let's instead define a 4-state enum solely for this use case, and place
it into the command's context. Note that END and FIN were already
aliases, which is why they were merged.
2022-05-06 18:13:35 +02:00
Willy Tarreau
3c69e08e96 CLEANUP: stick-table/cli: take the "show table" context definition out of the appctx
This makes use of the generic command context allocation so that the
appctx doesn't have to declare a specific one anymore. The context is
created during parsing. The code also uses st2 which deserves being
addressed in separate commit.
2022-05-06 18:13:35 +02:00
Willy Tarreau
0fd8f0e236 CLEANUP: proxy/cli: take the "show errors" context definition out of the appctx
This makes use of the generic command context allocation so that the
appctx doesn't have to declare a specific one anymore. The context is
created during parsing.

The code still has room for improvement, such as in the "flags" field
where bits are hard-coded, but they weren't modified.
2022-05-06 18:13:35 +02:00
Willy Tarreau
6177cfc3b5 CLEANUP: stream/cli: remove the now unneeded dump state from "show sess"
The state was a constant, let's remove what remains of the switch/case.
The code from the "case" statement was only reindented as can be checked
with "git show -b".
2022-05-06 18:13:35 +02:00
Willy Tarreau
bb4e289fa9 CLEANUP: stream/cli: remove the unneeded STATE_FIN state from "show sess"
This state is only an alias for "thr >= global.nbthread" which is the
sole condition that indicates the end and reaches it. Let's just drop
this state. There's only the STATE_LIST that's left.
2022-05-06 18:13:35 +02:00
Willy Tarreau
f3629f88ac CLEANUP: stream/cli: remove the unneeded init state from "show sess"
This state was only used to preset the list element. Now that we can
guarantee that the context can be properly preset during the parsing
we don't need this state anymore. The first pointer has to be set to
point to the first stream during the initial call which is detected
by the pointer not yet being set (null). Thanks to this we can also
remove one state check on the abort path.
2022-05-06 18:13:35 +02:00
Willy Tarreau
7fb591a4e4 CLEANUP: stream/cli: stop using appctx->st2 for the dump state
Let's instead define a 3-state enum solely for this use case, and place
it into the command's context.
2022-05-06 18:13:35 +02:00
Willy Tarreau
39f097d965 CLEANUP: stream/cli: take the "show sess" context definition out of the appctx
This makes use of the generic command context allocation so that the
appctx doesn't have to declare a specific one anymore. The context is
created during parsing.
2022-05-06 18:13:35 +02:00
Willy Tarreau
009e42bc59 CLEANUP: applet: make appctx_new() initialize the whole appctx
Till now, appctx_new() used to allocate an entry from the pool and
pass it through appctx_init() to initialize a debatable part of it that
didn't correspond anymore to the comments, and fill other fields. It's
hard to say what is fully initialized and what is not.

Let's get rid of that, and always zero the initialization (appctx are
not that big anyway, even with the cache there's no difference in
performance), and initialize what remains. this is cleaner and more
resistant to new field additions.

The appctx_init() function was removed.
2022-05-06 18:13:35 +02:00
Willy Tarreau
f12f32a0fa MINOR: applet: reserve some generic storage in the applet's context
Instead of using existing fields and having to put keyword-specific
contexts in the applet definition, let's have the appctx provide a
generic storage area that's currently large enough for existing CLI
commands and small applets, and a function to allocate that storage.

The function will be responsible for verifying that the requested size
fits in the area so that the caller doesn't need to add specific checks;
it is validated during development as this size is static and will
not change at runtime. In addition the caller doesn't even need to
free() the area since it's part of an existing context. For the
caller's convenience, a context pointer "svcctx" for the command is
also provided so that the allocated area can be placed there (or
possibly any other one in case a larger area is needed).

The struct's layout has been temporarily complicated by adding one
level of anonymous union on top of the "ctx" one. This will allow us
to preserve "ctx" during 2.6 for compatibility with possible external
code and get rid of it in 2.7. This explains why the diff extends to
the whole "ctx" union, but a "git show -b" shows that only one extra
layer was added. In order to make both the svcctx pointer and its
storage accessible without further enlarging the appctx structure,
both svcctx and the storage share the same storage as the ctx part.
This is done by having them placed in the union with a protected
overlapping area for svcctx, for which a shadow member is also
present in the storage area:

    union {
       void* svcctx;         // variable accessed by services
       struct {
           void *shadow;     // shadow of svcctx;
           char storage[];   // where most services store their data
       };
       union {               // older commands store here and ignore svcctx
          ...
       } ctx;
    };

I.e. new applications will use appctx->svcctx while older ones will be
able to continue to use appctx->ctx.*

The whole area (including the pointer's context) is zeroed before any
applet is initialized, and before CLI keyword processor's first invocation,
as it is an important part of the existing keyword processors, which makes
CLI keywords effectively behave like applets.
2022-05-06 18:13:35 +02:00
Willy Tarreau
1b948ef426 CLEANUP: ssl/cli: do not loop on unknown states in "add ssl crt-list" handler
The io_handler in "add ssl crt_list" is built around a "while" loop that
only makes forward progress and that doesn't handle its final state as
it's not supposed to be called again once reached. This makes the code
confusing because its construct implies an infinite loop for such a
state (or any other unhandled one). Let's just remove that unneeded loop.
2022-05-06 18:13:35 +02:00
Willy Tarreau
4fd9b4ddf0 BUG/MINOR: ssl/cli: fix "show ssl cert" not to mix cli+ssl contexts
The "show ssl cert" command mixes some generic pointers from the
"ctx.cli" struct with context-specific ones from "ctx.ssl" while both
are in a union. Amazingly, despite the use of both p0 and i0 to store
respectively a pointer to the current ckchs and a transaction id, there
was no overlap with the other pointers used during these operations,
but should these fields be reordered or slightly updated this will break.
Comments were added above the faulty functions to indicate which fields
they are using.

This needs to be backported to 2.5.
2022-05-06 18:13:35 +02:00
Willy Tarreau
4cf3ef8007 BUG/MINOR: ssl/cli: fix "show ssl crl-file" not to mix cli+ssl contexts
The "show ssl crl-file" command mixes some generic pointers from the
"ctx.cli" struct with context-specific ones from "ctx.ssl" while both
are in a union. It's fortunate that the p1 pointer in use is located
before the first one used (it overlaps with old_cafile_entry). But
should these fields be reordered or slightly updated this will break.

This needs to be backported to 2.5.
2022-05-06 18:13:35 +02:00
Willy Tarreau
06305798f7 BUG/MINOR: ssl/cli: fix "show ssl ca-file <name>" not to mix cli+ssl contexts
The "show ssl ca-file <name>" command mixes some generic pointers from
the "ctx.cli" struct and context-specific ones from "ctx.ssl" while both
are in a union. The i0 integer used to store the current ca_index overlaps
with new_crlfile_entry which is thus harmless for now but is at the mercy
of any reordering or addition of these fields. Let's add dedicated fields
into the ssl structure for this.

Comments were added on top of the affected functions to indicate what they
use.

This needs to be backported to 2.5.
2022-05-06 18:13:35 +02:00
Willy Tarreau
821c3b0b5e BUG/MINOR: ssl/cli: fix "show ssl ca-file/crl-file" not to mix cli+ssl contexts
The "show ca-file" and "show crl-file" commands mix some generic pointers
from the "ctx.cli" struct and context-specific ones from "ctx.ssl" while
both are in a union. It's fortunate that the p0 pointer in use is located
immediately before the first one used (it overlaps with next_ckchi_link,
and old_cafile_entry is safe). But should these fields be reordered or
slightly updated this will break.

Comments were added on top of the affected functions to indicate what they
use.

This needs to be backported to 2.5.
2022-05-06 18:13:35 +02:00
Willy Tarreau
1ae0c43244 BUG/MINOR: map/cli: make sure patterns don't vanish under "show map"'s init
When "show map" initializes itself, it first takes the reference to the
starting point under a lock, then releases it before switching to state
STATE_LIST, and takes the lock again. The problem is that it is possible
for another thread to remove the first element during this unlock/lock
sequence, and make the list run anywhere. This is of course extremely
unlikely but not impossible.

Let's initialize the pointer in the STATE_LIST part under the same lock,
which is simpler and more reliable.

This should be backported to all versions.
2022-05-06 18:13:35 +02:00
Willy Tarreau
2edaace575 BUG/MINOR: map/cli: protect the backref list during "show map" errors
In case of write error in "show map", the backref is detached but
the list wasn't locked when this is done. The risk is very low but
it may happen that two concurrent "show map" one of which would fail
or one "show map" failing while the same entry is being updated could
cause a crash.

This should be backported to all stable versions.
2022-05-06 18:13:35 +02:00
Willy Tarreau
4f9f157537 BUG/MINOR: proxy/cli: don't enumerate internal proxies on "show backend"
Commit e7f74623e ("MINOR: stats: don't output internal proxies (PR_CAP_INT)")
in 2.5 ensured we don't dump internal proxies on the stats page, but the
same is needed for "show backend", as since the addition of the HTTP client
it now appears there:

  $ socat /tmp/sock1 - <<< "show backend"
  # name
  <HTTPCLIENT>

This needs to be backported to 2.5.
2022-05-06 18:13:35 +02:00
Willy Tarreau
241a006d79 BUG/MEDIUM: cli: make "show cli sockets" really yield
This command was introduced in 1.8 with commit eceddf722 ("MEDIUM: cli:
'show cli sockets' list the CLI sockets") but its yielding doesn't work.
Each time it enters, it restarts from the last bind_conf but enumerates
all listening sockets again, thus it loops forever. The risk that it
happens in field is low but it easily triggers on port ranges after
400-500 sockets depending on the length of their addresses:

  global
     stats socket /tmp/sock1 level admin
     stats socket 192.168.8.176:30000-31000 level operator

  $ socat /tmp/sock1 - <<< "show cli sockets"
  (...)
  ipv4@192.168.8.176:30426 operator all
  ipv4@192.168.8.176:30427 operator all
  ipv4@192.168.8.176:30428 operator all
  ipv4@192.168.8.176:30000 operator all
  ipv4@192.168.8.176:30001 operator all
  ipv4@192.168.8.176:30002 operator all
  ^C

This patch adds the minimally needed restart point for the listener so
that it can easily be backported. Some more cleanup is needed though.
2022-05-06 18:13:35 +02:00
Willy Tarreau
4e047e7d0e BUG/MEDIUM: resolvers: make "show resolvers" properly yield
The "show resolvers" command is bogus, it tries to implement a yielding
mechanism except that if it yields it restarts from the beginning, until
it manages to fill the buffer with only line breaks, and faces error -2
that lets it reach the final state and exit.

The risk is low since it requires about 50 name servers to reach that
state, but it's not impossible, especially when using multiple sections.

In addition, the extraneous line breaks, if sent over an interactive
connection, will desynchronize the commands and make the client believe
the end was reached after the first nameserver. This cannot be fixed
separately because that would turn this bug into an infinite loop since
it's the line feed that manages to fill the buffer and stop it.

The fix consists in saving the current resolvers section into ctx.cli.p1
and the current nameserver into ctx.cli.p2.

This should be backported, but that code moved a lot since it was
introduced and has always been bogus. It looks like it has mostly
stabilized in 2.4 with commit c943799c86 so the fix might be backportable
to 2.4 without too much effort.
2022-05-06 18:13:35 +02:00
William Lallemand
89e236f246 BUG/MINOR: startup: usage() when no -cc arguments
Exit correctly with usage() instead of segfaulting when no argument
were passed to -cc.

Must be backported in 2.5.
2022-05-06 17:22:36 +02:00
William Lallemand
7867f63313 MEDIUM: resolvers: create a "default" resolvers section at startup
Try to create a "default" resolvers section at startup, but does not
display any error nor warning. This section is initialized using the
/etc/resolv.conf of the system.

This is opportunistic and with no guarantee that it will work (but it should
on most systems).

This is useful for the httpclient as it allows to use the DNS resolver
without any configuration in most of the cases.

The function is called from the httpclient_pre_check() function to
ensure than we tried to create the section before trying to initiate the
httpclient. But it is also called from the resolvers.c to ensure the
section is created when the httpclient init was disabled.
2022-05-06 17:02:15 +02:00
William Lallemand
0164a40c59 BUG/MINOR: tcp/http: release the expr of set-{src,dst}[-port]
Release the expression used by the set-{src,dst}[-port] actions so we
keep valgrind happy upon an exit or an haproxy -c.

Could be backported in every supported version.
2022-05-06 17:02:15 +02:00
Willy Tarreau
7831e0272e BUILD: debug: unify the definition of ha_backtrace_to_stderr()
It was both defined as ha_backtrace_to_stderr(void) and
ha_backtrace_to_stderr(), and tcc is not happy with this, so let's
adjust this tiny detail.
2022-05-06 15:16:19 +02:00
William Lallemand
e7f5776800 MINOR: resolvers: resolvers_new() create a resolvers with default values
Split the creation of the resolve structure from the parser to
resolvers_new();
2022-05-05 18:27:48 +02:00
William Lallemand
73edfe402e MINOR: resolvers: move the resolv.conf parser in parse_resolv_conf()
Move the resolv.conf parser from the cfg_parse_resolvers so it could be
used separately.

Some changes were made in the memprintf in order to use a char **
instead of a char *. Also the variable is tested before each memprintf
so could skip them if no warnmsg nor errmsg were set.
2022-05-05 17:38:48 +02:00
William Lallemand
106bd29dd0 MINOR: resolvers: cleanup alert/warning in parse-resolve-conf
Cleanup the alert and warning handling in the "parse-resolve-conf"
parser to use the errmsg and warnmsg variables and memprintf.

This will allow to split the parser and shut the alert/warning if
needed.
2022-05-05 17:33:42 +02:00
Christopher Faulet
d934e8d963 BUG/MEDIUM: mux-h1: Be able to handle trailers when C-L header was specified
The commit 2eb5243e7 ("BUG/MEDIUM: mux-h1: Set outgoing message to DONE when
payload length is reached") introduced a regression. An internal error is
reported when we try to forward a message with trailers while the
content-length header was specified. Indeed, this case does not exist for H1
messages but it is possible in H2.

This patch should solve the issue #1684. It must be backported as far as
2.4.
2022-05-05 09:39:43 +02:00
Christopher Faulet
2db904e86c BUG/MEDIUM: mux-fcgi: Be sure to never set EOM flag on an empty HTX message
This bug was already fixed at many places (stats, promex, lua) but the FCGI
multiplexer is also affected. When there is no content-length specified in
the response and when the END_REQUEST record is delayed, the response may be
truncated because an abort is erroneously detected. If the connection is not
closed because "keep-conn" option is set, the response is aborted at the end
of the server timeout.

This bug is a design issue with the HTX. It should be addressed. But it will
probably not be possible to backport them as far as 2.4. So, for now, the
only solution is to explicitly add an EOT block with the EOM flag in this
case.

This patch should fix the issue #1682. It must be backported as far as 2.4.
2022-05-05 09:24:55 +02:00
Christopher Faulet
c41f93c5cd BUG/MEDIUM: conn-stream: Only keep app layer flags of the endpoint on reset
The commit a6c4a4834 ("BUG/MEDIUM: conn-stream: Don't erase endpoint flags
on reset") was too laxy on reset. Only app layer flags must be preserved. On
reset, the endpoint is detached. Thus all flags set by the endpoint itself
or concerning its type must be removed.

Without this fix, we can experienced crashes when a stream is released while
a server connection attempt failed. Indeed, in this case, endpoint of the
backend conn-stream is reset. But the endpoint type is still set. Thus when
the stream is released, the endpoint is detached again.

This patch is 2.6-specific. No backport needed. This commit depends on the
previous one ("MINOR: conn-stream: Add mask from flags set by endpoint or
app layer").
2022-05-05 09:23:44 +02:00
William Lallemand
7c5a7ef32b MINOR: httpclient: allow ipv4 or ipv6 preference for resolving
The httpclient.resolvers.prefer global keyword allows to configure an
ipv4 or ipv6 preference when resolving. This could be useful in
environment where the ipv6 is not supported.
2022-05-04 16:14:42 +02:00
William Lallemand
8a734cbae3 MINOR: httpclient: configure the resolvers section to use
By default the httpclient uses the resolvers section whose ID is
"default", the httpclient.resolvers.id global option allows to configure
another section to use.
2022-05-04 16:14:35 +02:00
William Lallemand
683fbb86be MINOR: httpclient: allow to configure the ca-file
The global keyword httpclient.ssl.ca-file allows to configure the
ca-file used for the httpclient verify.
2022-05-04 16:14:35 +02:00
William Lallemand
6fce46a910 MEDIUM: httpclient: hard-error when SSL is configured
The hard_error_ssl flag is set when the configuration is explicitely
done for the ssl in the httpclient.

If no configuration was made, the features are simply disabled and no
alert is emitted.
2022-05-04 16:13:17 +02:00
William Lallemand
85af49c5c8 MINOR: httpclient: cleanup the error handling in init
Cleanup the error handling in the initialization so we rely on the
ERR_CODE and use memprintf() to set the errmsg before printing it at the
end of the functions.
2022-05-04 14:33:57 +02:00
William Lallemand
8b9a2df969 MINOR: init: exit() after pre-check upon error
Add a test on the err_code variable so we don't go further if one of the
pre-check callback failed.
2022-05-04 14:29:46 +02:00
William Lallemand
9ff95e2269 MINOR: httpclient: rename dash by dot in global option
Rename the httpclient-ssl-verify into httpclient.ssl.verify.
2022-05-04 13:52:29 +02:00
William Lallemand
853327390e MINOR: httpclient: handle unix and other socket types in dst
httpclient_set_dst() allows one to set the destination address instead
of using the one in the URL or resolving one from the host.
This function also support other types of socket like sockpair@, unix@,
anything that could be used on a server line.

In order to still support this behavior, the address must be set on the
backend in this particular case because the frontend connection does not
support anything other than ipv4 or ipv6.
2022-05-04 11:21:01 +02:00
William Lallemand
0e23526a2c CLEANUP: httpclient: remove the comment about resolving
remove the comment of httpclient_start which states there is no
resolver.
2022-05-04 11:21:01 +02:00
William Lallemand
1218d19921 MEDIUM: httpclient: allow address and port change for resolving
To allow the http-request set-dst to work for the httpclient DNS
resolving, some changes need to be done:

- The destination address need to be set in the frontend (s->csf->dst)
  instead of the backend (s->csb->dst) to be able to use
  tcp_action_req_set_dst()

- SRV_F_MAPPORTS need to be set on the proxy in order to allow the port
  change in alloc_dst_address()
2022-05-04 11:21:01 +02:00
William Lallemand
5392ff6e3c MEDIUM: httpclient: http-request rules for resolving
The httpclient_resolve_init() adds http-request actions which does the
resolving using the Host header of the HTTP request.

The parse_http_req_cond function is directly used over an array of http
rules.

The do-resolve rule uses the "default" resolvers section. If this
section does not exist in the configuration, the resolving is disabling.
2022-05-04 11:21:01 +02:00
William Lallemand
7f1df8ff1a MEDIUM: httpclient: remove url2sa to use a more flexible parser
The httpclient DNS resolver will need a more efficient URL parser which
splits the URL into parts and does not try to resolve.

httpclient_spliturl uses the http_uri_parser in order to split the URL
into several ist.

The result of the function host part is then processed into str2ip2(),
and fails if it it not an IP, allowing us to resolve the domain later.
2022-05-04 11:21:01 +02:00
Frédéric Lécaille
b57de07a21 BUG/MINOR: mux_quic: Dropped packet upon retransmission for closed streams
We rely on the largest ID which was used to open streams to know if the
stream we received STREAM frames for is closed or not. If closed, we return the
same status as the one for a STREAM frame which  was a already received one for
on open stream.
2022-05-03 10:13:40 +02:00
Frédéric Lécaille
d62240c9e5 BUG/MINOR: quic: Dropped retransmitted STREAM frames
It is possible that we continue to receive retransmitted STREAM frames after
the mux have been released. We rely on the ->rx.streams[].nb_streams counter
to check the stream was closed. If not, at this time we drop the packet.
2022-05-03 10:13:40 +02:00
Frédéric Lécaille
664741e1c5 MINOR: quic: Make the quic_conn be aware of the number of streams
This is required when the retransmitted frame types when the mux is released.
We add a counter for the number of streams which were opened or closed by the mux.
After the mux has been released, we can rely on this counter to know if the STREAM
frames are retransmitted ones or not.
2022-05-03 10:13:40 +02:00
Willy Tarreau
0367b4cf63 MINOR: session: get rid of the now unused SESS_FL_ADDR_*_SET flags
That's similar to what was done for conn_streams and connections. The
flags were only set exactly when the relevant pointers were allocated,
so better test the pointer than the flag and stop setting the flag.
2022-05-02 17:51:51 +02:00
Willy Tarreau
030b3e6bcc MINOR: connection: get rid of the CO_FL_ADDR_*_SET flags
Just like for the conn_stream, now that these addresses are dynamically
allocated, there is no single case where the pointer is set without the
corresponding flag, and the flag is used as a permission to dereference
the pointer. Let's just replace the test of the flag with a test of the
pointer and remove all flag assignment. This makes the code clearer
(especially in "if" conditions) and saves the need for future code to
think about properly setting the flag after setting the pointer.
2022-05-02 17:47:46 +02:00
Willy Tarreau
158b6cf102 CLEANUP: protocol: make sure the connect_* functions always receive a dst
Some of the protocol-level ->connect() functions currently dereference
the connection's destination address while others test it and return an
error. There's normally no more non-bogus code path that calls such
functions without a valid destination address on the connection, so
let's unify these functions and just place a BUG_ON() there, and drop
the useless test that's supposed to return an internal error.
2022-05-02 17:47:31 +02:00
Willy Tarreau
03bd3952a6 MEDIUM: stream: remove the confusing SF_ADDR_SET flag
This flag is no longer needed now that it must always match the presence
of a destination address on the backend conn_stream. Worse, before previous
patch, if it were to be accidently removed while the address is present, it
could result in a leak of that address since alloc_dst_address() would first
be called to flush it.

Its usage has a long history where addresses were stored in an area shared
with the connection, but as this is no longer the case, there's no reason
for putting this burden onto application-level code that should not focus
on setting obscure flags.

The only place where that made a small difference is in the dequeuing code
in case of queue redistribution, because previously the code would first
clear the flag, and only later when trying to deal with the queue, would
release the address. It's not even certain whether there would exist a
code path going to connect_server() without calling pendconn_dequeue()
first (e.g. retries on queue timeout maybe?).

Now the pendconn_dequeue() code will rely on SF_ASSIGNED to decide to
clear and release the address, since that flag is always set while in
a server's queue, and its clearance implies that we don't want to keep
the address. At least it remains consistent and there's no more risk of
leaking it.
2022-05-02 16:56:01 +02:00
Willy Tarreau
b3f0d42a1d CLEANUP: backend: make alloc_{bind,dst}_address() idempotent
These functions dynamically allocate a source or destination address but
start by clearing the previous one. There's a non-null risk of leaking
addresses there in case of misuse. Better have them do nothing if the
address was already allocated.
2022-05-02 16:20:36 +02:00
Amaury Denoyelle
291ee25696 BUG/MINOR: h3: fix parsing of unknown frame type with null length
HTTP/3 implementation must ignore unknown frame type to support protocol
evolution. Clients can deliberately use unknown type to test that the
server is conformant : this principle is called greasing.

Quiche client uses greasing on H3 frame type with a zero length frame.
This reveals a bug in H3 parsing code which causes the transfer to be
interrupted. Fix this by removing the break statement on ret variable.
Now the parsing loop is only interrupted if input buffer is empty or the
demux is blocked.

This should fix http/3 freeze transfers with the quiche client. Thanks
to Lucas Pardue from Cloudflare for his report on the bug. Frédéric
Lecaille quickly found the source of the problem which helps me to write
this patch.
2022-05-02 11:36:42 +02:00
Amaury Denoyelle
f1fc0b393b MINOR: mux-quic: support full request channel buffer
If the request channel buffer is full, H3 demuxing must be interrupted
on the stream until some read is performed. This condition is reported
if the HTX stream buffer qcs.rx.app_buf is full.

In this case, qcs instance is marked with a new flag QC_SF_DEM_FULL.
This flag cause the H3 demuxing to be interrupted. It is cleared when
the HTX buffer is read by the conn-stream layer through rcv_buf
operation.

When the flag is cleared, the MUX tasklet is woken up. However, as MUX
iocb does not treat Rx for the moment, this is useless. It must be fix
to prevent possible freeze on POST transfers.

In practice, for the moment the HTX buffer is never full as the current
Rx code is limited by the quic-conn receive buffer size and the
incomplete flow-control implementation. So for now this patch is not
testable under the current conditions.
2022-05-02 11:19:02 +02:00
Frédéric Lécaille
c40e19d711 BUG/MINOR: quic: Missing time threshold multiplifier for loss delay computation
It seems this multiplier ended up in oblivion. Indeed a multiplier must be
applied to the loss delay expressed as an RTT multiplier: 9/8.

So, some packets were detected as lost too soon, leading to be retransmitted too
early!
2022-04-29 16:46:56 +02:00
Frédéric Lécaille
1601395063 MINOR: quic: moving code for QUIC loss detection
qc_qc_packet_loss_lookup() is definitively a QUIC loss detection function.
2022-04-29 16:46:56 +02:00
Frédéric Lécaille
88e5741c53 CLEANUP: quic: Remaining fprintf() debug trace
Development remaining trace.
2022-04-29 16:46:56 +02:00
Frédéric Lécaille
1231d3c179 MINOR: quic: Drop 0-RTT packets without secrets
If we received 0-RTT packets and no secrets were provided by the TLS stack
we must drop them.
2022-04-29 16:46:56 +02:00
Amaury Denoyelle
74cf237ecd MEDIUM: quic: do not ack packet with invalid STREAM
If the MUX cannot handle immediately nor buffer a STREAM frame, the
packet containing it must not be acknowledge. This is in conformance
with the RFC9000.

qcc_recv() return codes have been adjusted to differentiate an invalid
frame with an already fully received offset which must be acknowledged.
2022-04-29 16:16:19 +02:00
Amaury Denoyelle
d46e335683 MEDIUM: quic: do not ACK packet with STREAM if MUX not present
If a packet contains a STREAM frame but the MUX is not allocated, the
frame cannot be enqueued. According to the RFC9000, we must not
acknowledge the packet under this condition.

This may prevents a bug with firefox which keeps trying on refreshing
the web page. This issue has already been detected before closing state
implementation : haproxy wasn't emitted CONNECTION_CLOSE and keeps
acknowledge STREAM frames despite not handle them.

In the future, it might be necessary to respond with a CONNECTION_CLOSE
if the MUX has already been freed.
2022-04-29 16:15:47 +02:00
Willy Tarreau
4173f4ea29 BUG/MINOR: conn_stream: do not confirm a connection from the frontend path
In issue #1468 it was reported that sometimes server-side connection
attempts were only validated after the "timeout connect" value, and
that would only happen with an H2 client. A long code analysis with the
output dumps showed only one possible call path: an I/O event on the
frontend while reading had just been disabled calls h2_wake() which in
turns wakes cs_conn_io_cb(), which tries cs_conn_process() and cs_notify(),
which sees that the other side is not blocked (already in CS_ST_CON)
and tries cs_chk_snd() on it. But on that side the connection had just
finished to be set up and not yet woken the stream up, cs_notify()
would then call cs_conn_send() which succeeds and passes the connection
to CS_ST_RDY. The problem is that nothing new happened on the frontend
side so there's no reason to wake the stream up and the backend-side
conn_stream remains in CS_ST_RDY state with the stream never being
woken up.

Once the "timeout connect" strikes, process_stream() is woken up and
finds the connection finally setup, so it ignores the timeout and goes
on.

The number of conditions to meet to reproduce this is huge, which also
explains why the reporter says it's "occasional" and we were never able
to reproduce it in the lab. It needs at least reads to be disabled and
immediately re-enabled on the frontend side (e.g. buffer full) with an
I/O even reported before the poller had an opportunity to be disabled
but with no subscribe being reinstalled, so that sock_conn_iocb() has
no other choice but calling h2_wake(), and exactly at the same time
the backend connection must finish to set up so that it was not yet
reported by the poller, the data were sent and the polling for writes
disabled.

Several factors are to be considered here:
  - h2_wake() should probably not call h2_wake_some_streams() for
    ret >= 0 (common case), but only if some special event is reported
    for at least one stream; that part is sensitive though as in the
    past we managed to lose some rare cases (e.g. restart processing
    after a pause), and such wakeups are extremely rare so we'd better
    make that effort once in a while.

  - letting a lazy forward attempt on the frontend confirm a backend
    connection establishment is too smart to be reliable. That wasn't
    in fact the intent and it's inherited from the very old code where
    muxes didn't exist and where it was guaranteed that an even at this
    layer would wake everyone up.

Here the best thing to do is to refrain from attempting to forward data
until the connection is confirmed. This will let the poller report the
connect() event to the backend side which will process it as it should
and does in all other cases.

Thanks to Jimmy Crutchfield for having reported useful traces and
tested patches.

This will have to be backported to all stable branches after some
observation. Before 2.6 the function is stream_int_chk_snd_conn(),
and the flag to remove is SI_SB_CON.
2022-04-29 15:32:14 +02:00
Christopher Faulet
0055d5693e MINOR: httpclient: Don't use co_set_data() to decrement output
The use of co_set_data() should be strictly limited to setting the amount of
existing data to be transmitted. It ought not be used to decrement the
output after the data have left the buffer, because doing so involves
performing incorrect calculations using co_data() that still comprises data
that are not in the buffer anymore. Let's use c_rew() for this, which is
made exactly for this purpose, i.e. decrement c->output by as much as
requested.
2022-04-29 14:12:42 +02:00
Christopher Faulet
6b4f1f64a8 BUG/MINOR: httpclient: Count metadata in size to transfer via htx_xfer_blks()
When HTX blocks are transfer from the HTTP client context to the request
channel, via htx_xfer_blks() function, the metadata must also be counted, in
addition to the data size. Otherwise, expected payload size will not be
copied because the metadata of an HTX block (8 bytes) will be reserved. And
if the payload size is lower than 8 bytes, nothing will be copied. Thus only
a zero-copy will be able to copy the payload.

This issue is 2.6-specific, no backport is needed.
2022-04-29 14:12:42 +02:00
Christopher Faulet
534645d6c0 BUG/MEDIUM: httpclient: Fix loop consuming HTX blocks from the response channel
When the HTTP client consumes the response, it loops on the HTX message to
copy blocks content and it removes blocks by calling htx_remove_blk(). But
this function removes a block and returns the next one in the HTX
message. The result must be used instead of using htx_get_next(). It is
especially important because the block used in htx_get_next() loop was
removed. It only works because the message is not defragmented during the
loop.

In addition, the loop on the response was simplified to iter on blocks
instead of positions.

This patch must be backported to 2.5.
2022-04-29 14:12:42 +02:00
Christopher Faulet
a6c4a48341 BUG/MEDIUM: conn-stream: Don't erase endpoint flags on reset
Only CS_EP_ERROR flag is now removed from the endpoint when a reset is
performed. When a new the endpoint is allocated, flags are preserved. It is
the caller responsibility to remove other flags, depending on its need.

Concretly, during a connection retry or a L7 retry, we must preserve
flags. In tcpcheck and the CLI, we reset flags.

This patch is 2.6-specific. No backport needed.
2022-04-29 14:12:42 +02:00
William Lallemand
04994de642 BUG/MINOR: httpclient/ssl: use the correct verify constant
The SSL_SERVER_VERIFY_* constants were incorrectly set on the httpclient
server verify. The right constants are SSL_SOCK_VERIFY_* .

This could cause issues when using "httpclient-ssl-verify" or when the
SSL certificates can't be loaded.

No backport needed
2022-04-28 19:35:21 +02:00
Frédéric Lécaille
3e26698f89 MINOR: quic: Drop 0-RTT packets if not allowed
Drop the 0-RTT packets for a listener without early data configuration enabled.
2022-04-28 16:22:40 +02:00
Frédéric Lécaille
4646cf3b70 CLEANUP: quic: Rely on the packet length set by qc_lstnr_pkt_rcv()
This function is used to parse the QUIC packets carried by a UDP datagram.
When a correct packet could be found, the ->len RX packet structure value
is set to the packet length value. On the contrary, it is set to the remaining
number of bytes in the UDP datagram if no correct QUIC packet could be found.
So, there is no need to make this function return a status value. It allows
the caller to parse any QUIC packet carried by a UDP datagram without this.
2022-04-28 16:22:40 +02:00
Frédéric Lécaille
87373e7269 BUG/MINOR: quic: Missing Initial packet length check
Any client Initial packet carried in a datagram smaller than QUIC_INITIAL_PACKET_MINLEN(200)
bytes must be discarded. This does not mean we must discard the entire datagram.
So we must at least try to parse the packet length before dropping the packet
and return its length from qc_lstnr_pkt_rcv().
2022-04-28 16:22:40 +02:00
Frédéric Lécaille
77cb38d22d BUG/MEDIUM: quic: Possible crash on STREAM frame loss
A crash is possible under such circumtances:
    - The congestion window is drastically reduced to its miniaml value
    when a quic listener is experiencing extreme packet loss ;
    - we enqueue several STREAM frames to be resent and some of them could not be
    transmitted ;
    - some of the still in flight are acknowledged and trigger the
    stream memory releasing ;
    - when we come back to send the remaing STREAM frames, haproxy
    crashes when it tries to build them.

To fix this issue, we mark the STREAM frame as lost when detected as lost.
Then a lookup if performed for the stream the STREAM frames are attached
to before building them. They are released if the stream is no more available
or the data range of the frame is consumed.
2022-04-28 16:22:40 +02:00
Frédéric Lécaille
dafbde6c8c MINOR: quic: Wake up the mux to probe with new data
When we have to probe the peer, we must first try to send new data. This is done
here waking up the mux after having set the number of maximum number of datagrams
to send to QUIC_MAX_NB_PTO_DGRAMS (2). Of course, this is only the case if the
mux was subscribed to SEND events.
2022-04-28 16:22:40 +02:00
Frédéric Lécaille
d8b798d7ef BUG/MINOR: quic: Traces fix about remaining frames upon packet build failure 2022-04-28 16:22:40 +02:00
Frédéric Lécaille
834399c24a BUG/MINOR: quic: Avoid sending useless PADDING frame
This may happen in rare cases with extreme packet loss (30% for both TX and RX)
which leads the congestion window to decrease down to its minimal value (two
datagrams). Under such circumtances, no ack-eliciting frame can be added to
a packet by qc_build_frms(). In this case we must cancel the packet building
process if there is no ACK or probe (PING frame) to send.
2022-04-28 16:22:40 +02:00
Frédéric Lécaille
573b56b774 BUG/MINOR: quic: Wrong returned status by qc_build_frms()
This function must return a successful status as soon as it could be build
a frame to be embedded by a packet. This behavior was broken by the last
modifications. This was due to a dangerous "ret = 1" statement inside
a loop. This statement must be reach only if we go out of a switch/case
after a "break" statement.
Add comments to mention this information.
2022-04-28 16:22:40 +02:00
Frédéric Lécaille
337108ecda MINOR: quic: Do not send ACK frames when probing
When we are probing, we do not receive packets, furthermore all ACK frames have
already been sent. This is useless to send ACK when probing the peer. This
modification does not reset the flag which marks the connection as requiring an
ACK frame to be sent. If this is the case, this will be taken into an account
by after the probing process.
2022-04-28 16:22:40 +02:00
Frédéric Lécaille
7aef5f4c3f MEDIUM: quic: Enable the new datagram probing process
Make the two I/O handlers quic_conn_io_cb() and quic_conn_app_io_cb() call
qc_dgrams_retransmit() after probing retransmissions need was detected by
the timer task (qc_process_timer()).
We must modify qc_prep_pkts() to support QUIC_TLS_ENC_LEVEL_NONE as <next_tel>
parameter when called from qc_dgrams_retransmit().
2022-04-28 16:22:40 +02:00
Frédéric Lécaille
da342556c3 MEDIUM: quic: Mark copies of acknowledged frames as acknowledged
We call qc_release_frm() to do so from this function everywhere a frame
is released.
2022-04-28 16:22:40 +02:00
Frédéric Lécaille
1809c33d6e MINOR: quic: Mark packets as probing with old data
When probing retranmissions with old data are needed for the connection we
mark the packets as probing with old data to track them when acknowledged:
we do not resend frames with old data when lost.
2022-04-28 16:22:40 +02:00
Frédéric Lécaille
3e3a621447 MINOR: quic: old data distinction for qc_send_app_pkt()
Modify qc_send_app_pkt() to distinguish the case where it sends new data
against the case where it sends old data during probing retransmissions.
We add <old_data> boolean parameter to this function to do so. The mux
never directly send old data when probing retransmissions are needed by
the connection.
2022-04-28 16:22:40 +02:00
Frédéric Lécaille
96367158ab MEDIUM: quic: qc_requeue_nacked_pkt_tx_frms() rework
This function is used to requeue the TX frames from TX packets which have
been detected as lost. The modifications consist in avoiding resending frames from
duplicated frames used to probe the peer. This is useless. Only the original
frames loss must be taken into an account because detected as lost before
the retransmitted frames. If these latter are also detected as lost, other
duplicated frames would have been retransmitted before their loss detection.
2022-04-28 16:22:40 +02:00
Frédéric Lécaille
e248e378c8 MEDIUM: quic: Retransmission functions rework
qc_prep_fast_retrans() and qc_prep_hdshk_fast_retrans() are modified to
take two list of frames as parameters. Two lists are needed for
qc_prep_hdshk_fast_retrans() to build datagrams with two packets during
handshake. qc_prep_fast_retrans() needs two lists of frames to be used
to send two datagrams with one list by datagram.
2022-04-28 16:22:40 +02:00
Frédéric Lécaille
a9568411e4 MEDIUM: quic: New functions for probing rework
We want to be able to resend frames from list of frames during handshakes to
resend datagrams with the same frames as during the first transmissions.
This leads to decrease drasctically the chances of frame fragmentation due to
variable lengths of the packet fields. Furthermore the frames were not duplicated
when retransmitted from a packet to another one. This must be the case only during
packet loss dectection.

qc_dup_pkt_frms() is there to duplicate the frames from an input list to an output
list. A distinction is made between STREAM frames and the other ones because we
can rely on the "acknowledged offset" the aim of which is to track the number
of bytes which were acknowledged from TX STREAM frames.

qc_release_frm() in addition to release the frame passed as parameter, also mark
the duplicate STREAM frames as acknowledeged.

qc_send_hdshk_pkts() is the qc_send_app_pkts() counterpart to send datagrams from
at most two list of frames to be able to coalesced packets from two different
packet number spaces

qc_dgrams_retransmit() is there to probe the peer with datagrams depending on the
need of the packet number spaces which must be flag with QUIC_FL_PKTNS_PROBE_NEEDED
by the PTO timer task (qc_process_timer()).
2022-04-28 16:22:40 +02:00
Frédéric Lécaille
3ef729a643 MINOR: quic: process_timer() rework
Add QUIC_FL_CONN_RETRANS_NEEDED connection flag definition to mark a quic_conn
struct as needing a retranmission.
Add QUIC_FL_PKTNS_PROBE_NEEDED to mark a packet number space as needing a
datagram probing.
Set these flags from process_timer() to trigger datagram probings.
Do not initiate anymore datagrams probing from any quic encryption level.
This will be done from the I/O handlers (quic_conn_io_cb() during handshakes and
quic_conn_app_io_cb() after handshakes).
2022-04-28 16:22:40 +02:00
Frédéric Lécaille
e87b3ee9f5 MINOR: quic: Add traces about TX frame memory releasing
Add such traces in qc_treat_acked_tx_frm(). This should be helpful to track memory
leak issues for TX frames.
2022-04-28 16:22:40 +02:00
Frédéric Lécaille
b44cbc68a6 MINOR: quic: Do not retransmit frames from coalesced packets
Add QUIC_FL_TX_PACKET_COALESCED flag to mark a TX packet as coalesced with others
to build a datagram.
Ensure we do not directly retransmit frames from such coalesced packets. They must
be retransmitted from their packet number spaces to avoid duplications.
2022-04-28 16:22:40 +02:00
Frédéric Lécaille
b917191817 MINOR: quic: Prepare quic_frame struct duplication
We want to track the frames which have been duplicated during retransmissions so
that to avoid uselessly retransmitting frames which would already have been
acknowledged. ->origin new member is there to store the frame from which a copy
was done, ->reflist is a list to store the frames which are copies.
Also ensure all the frames are zeroed and that their ->reflist list member is
initialized.
Add QUIC_FL_TX_FRAME_ACKED flag definition to mark a TX frame as acknowledged.
2022-04-28 16:22:40 +02:00
Frédéric Lécaille
fc88844d2c MINOR: quic: Improve qc_prep_pkts() flexibility
We want to be able to chosse the list of frames we want to prepare in packets
to be send. This is to modify the retransmission process (to come).
2022-04-28 16:22:40 +02:00
Amaury Denoyelle
03cc62c840 MINOR: quic: decode as much STREAM as possible
Add a loop in the bidi STREAM function. This will call repeatdly
qcc_decode_qcs() and dequeue buffered frames.

This is useful when reception of more data is interrupted because the
MUX buffer was full. qcc_decode_qcs() has probably free some space so it
is useful to immediatly retry reception of buffered frames of the qcs
tree.

This may fix occurences of stalled Rx transfers with large payload.
Note however that there is still room for improvment. The conn-stream
layer is not able at this moment to retrigger demuxing. This is because
the mux io-handler does not treat Rx : this may continue to cause
stalled tranfers.
2022-04-28 16:10:10 +02:00
Amaury Denoyelle
48f01bda86 MINOR: h3: support DATA demux if buffer full
Previously, h3 layer was not able to demux a DATA frame if not fully
received in the Rx buffer. This causes evident limitation and prevents
to be able to demux a frame bigger than the buffer.

Improve h3_data_to_htx() to support partial frame demuxing. The demux
state is preserved in the h3s new fields : this is useful to keep the
current type and length of the demuxed frame.
2022-04-28 15:44:19 +02:00
Amaury Denoyelle
67e92d3652 MINOR: h3: implement h3 stream context
Define a new structure h3s used to provide context for a H3 stream. This
structure is allocated and stored in the qcs thanks to previous commit
which provides app-layer context storage.

For now, h3s is empty. It will soon be completed to be able to support
stateful demux : this is required to be able to demux an incomplete
frame if the rx buffer is full.
2022-04-28 15:44:19 +02:00
Amaury Denoyelle
47447af1ef MINOR: mux-quic: add a app-layer context in qcs
Define 2 new callback for qcc_app_ops : attach and detach. They are
called when a qcs instance is respectively allocated and freed. If
implemented, they can allocate a custom context stored in the new
abstract field ctx of qcs.

For now, h3 and hq-interop does not use these new callbacks. They will
be soon implemented by the h3 layer to allocate a context used for
stateful demuxing.

This change is required to support the demuxing of H3 frames bigger than
a buffer.
2022-04-28 15:44:19 +02:00
Amaury Denoyelle
314578a54f MINOR: h3: change frame demuxing API
Edit the functions used for HEADERS and DATA parsing. They now return
the number of bytes handled.

This change will help to demux H3 frames bigger than the buffer.
2022-04-28 15:44:19 +02:00
Amaury Denoyelle
3df8ca0a4d MINOR: mux-quic: partially copy Rx frame if almost full buf
Improve the reception for STREAM frames. In qcc_recv(), if the frame is
bigger than the remaining space in rx buffer, do not reject it wholly.
Instead, copy as much data as possible. The rest of the data is
buffered.

This is necessary to handle H3 frames bigger than a buffer. The H3 code
does not demux until the frame is complete or the buffer is full.
Without this, the transfer on payload larger than the Rx buffer can
rapidly freeze.
2022-04-28 15:42:21 +02:00
Amaury Denoyelle
30f23f53d2 BUG/MEDIUM: h3: fix use-after-free on mux Rx buffer wrapping
Handle wrapping buffer in h3_data_to_htx(). If data is wrapping, first
copy the contiguous data, then copy the data in front of the buffer.

Note that h3_headers_to_htx() is not able to handle wrapping data. For
the moment, a BUG_ON was added as a reminder. This cas never happened,
most probably because HEADERS is the first frame of the stream.
2022-04-28 15:18:20 +02:00