BUG/MEDIUM: mux-h1: Set outgoing message to DONE when payload length is reached
When a message is sent, we can switch it state to MSG_DONE if all the
announced payload was processed. This way, if the EOM flag is not set on the
message when the last expected data block is processed, the message can
still be set to MSG_DONE state.
This bug is related to the previous ones. There is a design issue with the
HTX since the 2.4. When the EOM HTX block was replaced by a flag, I tried
hard to be sure the flag is always set with the last HTX block on a
message. It works pretty well for all messages received from a client or a
server. But for internal messages, it is not so simple. Because applets
cannot always properly handle the end of messages. So, there are some cases
where the EOM flag is set on an empty message.
As a workaround, for chunked messages, we can add an EOT HTX block. It does
the trick. But for messages with a content-length, there is no empty DATA
block. Thus, the only way to be sure the end of the message was reached in
this case is to detect it in the H1 multiplexr.
We already count the amount of data processed when the payload length is
announced. Thus, we must only switch the message in DONE state when last
bytes of the payload are received. Or when the EOM flag is received of
course.
BUG/MEDIUM: promex: Be sure to never set EOM flag on an empty HTX message
It is the same bug than "BUG/MEDIUM: stats: Be sure to never set EOM flag on
an empty HTX message". We must be sure to set the EOM flag on a non empyt
message to be sure the mux on the client will properly handle
shutdowns. Otherwise, it may miss the end of the message and considers any
shutdown as an abort.
This patch must be backported as far as 2.4. On previous version there is
still the EOM HTX block.
BUG/MEDIUM: hlua: Don't set EOM flag on an empty HTX message in HTTP applet
In a lua HTTP applet, when the script is finished, we must be sure to not
set the EOM on an empty message. Otherwise, because there is no data to
send, the mux on the client side may miss the end of the message and
consider any shutdown as an abort.
See "UG/MEDIUM: stats: Be sure to never set EOM flag on an empty HTX
message" for details.
This patch must be backported as far as 2.4. On previous version there is
still the EOM HTX block.
BUG/MEDIUM: stats: Be sure to never set EOM flag on an empty HTX message
During the last call to the stats I/O handle, it is possible to have nothing
to dump. It may happen for many reasons. For instance, all remaining proxies
are disabled or they don't match the specified scope. In HTML or in JSON, it
is not really an issue because there is a footer. So there are still some
data to push in the response channel buffer. In CSV, it is a problem because
there is no footer. It means it is possible to finish the response with no
payload at all in the HTX message. Thus, the EOM flag may be added on an
empty message. When this happens, a shutdown is performed on an empty HTX
message. Because there is nothing to send, the mux on the client side is not
notified that the message was properly finished and interprets the shutdown
as an abort.
The response is chunked. So an abort at this stage means the last CRLF is
never sent to the client. All data were sent but the message is invalid
because the response chunking is not finished. If the reponse is compressed,
because of a similar bug in the comppression filter, the compression is also
aborted and the content is truncated because some data a lost in the
compression filter.
It is design issue with the HTX. It must be addressed. And there is an
opportunity to do so with the recent conn-stream refactoring. It must be
carefully evaluated first. But it is possible. In the means time and to also
fix stable versions, to workaround the bug, a end-of-trailer HTX block is
systematically added at the end of the message when the EOM flag is set if
the HTX message is empty. This way, there are always some data to send when
the EOM flag is set.
Note that with a H2 client, it is only a problem when the response is
compressed.
This patch should fix the issue #1478. It must be backported as far as
2.4. On previous versions there is still the EOM block.
BUG/MINOR: fcgi-app: Don't add C-L header on response to HEAD requests
In the FCGI app, when a full response is received, if there is no
content-length and transfer-encoding headers, a content-length header is
automatically added. This avoid, as far as possible to chunk the
response. This trick was added because, most of time, scripts don"t add
those headers.
But this should not be performed for response to HEAD requests. Indeed, in
this case, there is no payload. If the payload size is not specified, we
must not added it by hand. Otherwise, a "content-length: 0" will always be
added while it is not the real payload size (unknown at this stage).
This patch should solve issue #1639. It must be backported as far as 2.2.
Define a new API to notify the MUX from the quic-conn when the
connection is about to be closed. This happens in the following cases :
- on idle timeout
- on CONNECTION_CLOSE emission or reception
The MUX wake callback is called on these conditions. The quic-conn
QUIC_FL_NOTIFY_CLOSE is set to only report once. On the MUX side,
connection flags CO_FL_SOCK_RD_SH|CO_FL_SOCK_WR_SH are set to interrupt
future emission/reception.
This patch is the counterpart to
"MEDIUM: mux-quic: report CO_FL_ERROR on send".
Now the quic-conn is able to report its closing, which may be translated
by the MUX into a CO_FL_ERROR on the connection for the upper layer.
This allows the MUX to properly react to the QUIC closing mechanism for
both idle-timeout and closing/draining states.
Complete the error reporting. For each attached streams, if CO_FL_ERROR
is set, mark them with CS_FL_ERR_PENDING|CS_FL_ERROR. This will notify
the upper layer to trigger streams detach and release of the MUX.
This reporting is implemented in a new function qc_wake_some_streams(),
called by qc_wake(). This ensures that a lower-layer error is quickly
reported to the individual streams.
Mark the connection with CO_FL_ERROR on qc_send() if the socket Tx is
closed. This flag is used by the upper layer to order a close on the
MUX. This requires to check CO_FL_ERROR in qcc_is_dead() to process to
immediate MUX free when set.
The qc_wake() callback has been completed. Most notably, it now calls
qc_send() to report a possible CO_FL_ERROR. This is useful because
qc_wake() is called by the quic-conn on imminent closing.
Note that for the moment the error flag can never be set because the
quic-conn does not report when the Tx socket is closed. This will be
implemented in a following patch.
Add a new app layer operation is_active. This can be used by the MUX to
check if the connection can be considered as active or not. This is used
inside qcc_is_dead as a first check.
For example on HTTP/3, if there is at least one bidir client stream
opened the connection is active. This explicitly ignore the uni streams
used for control and qpack as they can never be closed during the
connection lifetime.
MINOR: mux-quic: adjust timeout to accelerate closing
Improve timeout handling on the MUX. When releasing a stream, first
check if the connection can be considered as dead and should be freed
immediatly. This allows to liberate resources faster when possible.
If the connection is still active, ensure there is no attached
conn-stream before scheduling the timeout. To do this, add a nb_cs field
in the qcc structure.
BUG/MINOR: fix memleak on quic-conn streams cleaning
When freeing a quic-conn, the streams resources attached to it must be
cleared. This code is already implemented but the streams buffer was not
deallocated.
Fix this by using the function qc_stream_desc_free. This existing
function centralize all operations to properly free all streams
elements, attached both to the MUX and the quic-conn.
This fixes a memory leak which can happen for each released connection.
This flag was used to notify the MUX about a CONNECTION_CLOSE frame
reception. It is now unused on the MUX side and can be removed. A new
mechanism to detect quic-conn closing will be soon implemented.
BUG/MEDIUM: quic: ensure quic-conn survives to the MUX
Rationalize the lifetime of the quic-conn regarding with the MUX. The
quic-conn must not be freed if the MUX is still allocated.
This simplify the MUX code when accessing the quic-conn and removed
possible segfaults.
To implement this, if the quic-conn timer expired, the quic-conn is
released only if the MUX is not allocated. Else, the quic-conn is
flagged with QUIC_FL_CONN_EXP_TIMER. The MUX is then responsible
to call quic_close() which will free the flagged quic-conn.
New received packets after sending CONNECTION_CLOSE frame trigger a new
CONNECTION_CLOSE frame to be sent. Each time such a frame is sent we
increase the number of packet required to send another CONNECTION_CLOSE
frame.
Rearm only one time the idle timer when sending a CONNECTION_CLOSE frame.
The request buffering is required for doing l7 retry. The IO handler of
the httpclient need to be rework for that.
This patch change the IO handler so it copies partially the data instead
of swapping buffer. This is needed because the b_xfer won't never work
if the destination buffer is not empty, which is the case when
buffering.
BUG/MINOR: ssl/cli: Remove empty lines from CLI output
There were empty lines in the output of "show ssl ca-file <cafile>" and
"show ssl crl-file <crlfile>" commands when an empty line should only
mark the end of the output. This patch adds a space to those lines.
Nikola Sale [Sun, 3 Apr 2022 16:11:53 +0000 (18:11 +0200)]
MINOR: sample: converter: Add add_item convertor
This new converter is similar to the concat converter and can be used to
build new variables made of a succession of other variables but the main
difference is that it does the checks if adding a delimiter makes sense as
wouldn't be the case if e.g the current input sample is empty. That
situation would require 2 separate rules using concat converter where the
first rule would have to check if the current sample string is empty before
adding a delimiter. This resolves GitHub Issue #1621.
BUG/MINOR: ssl: continue upon error when opening a directory w/ ca-file
Previous patch was accidentaly breaking upon an error when itarating
through a CA directory. This is not the expected behavior, the function
must start processing the other files after the warning.
MEDIUM: ssl: allow loading of a directory with the ca-file directive
This patch implements the ability to load a certificate directory with
the "ca-file" directive.
The X509_STORE_load_locations() API does not allow to cache a directory
in memory at startup, it only references the directory to allow a lookup
of the files when needed. But that is not compatible with the way
HAProxy works, without any access to the filesystem.
The current implementation loads every ".pem", ".crt", ".cer", and
".crl" available in the directory which is what is done when using
c_rehash and X509_STORE_load_locations(). Those files are cached in the
same X509_STORE referenced by the directory name. When looking at "show ssl
ca-file", everything will be shown in the same entry.
This will eventually allow to load more easily the CA of the system,
which could already be done with "ca-file /etc/ssl/certs" in the
configuration.
Loading failure intentionally emit a warning instead of an alert,
letting HAProxy starts when one of the files can't be loaded.
Known limitations:
- There is a bug in "show ssl ca-file", once the buffer is full, the
iohandler is not called again to output the next entries.
- The CLI API is kind of limited with this, since it does not allow to
add or remove a entry in a particular ca-file. And with a lot of
CAs you can't push them all in a buffer. It probably needs a "add ssl
ca-file" like its done with the crt-list.
As suggested in the comment, it's possible to read 32 bits at once in
big-endian order, and now we have the functions to do this, so let's
do it. This reduces the code on the fast path by 31 bytes on x86, and
more importantly performs single-operation 32-bit reads instead of
playing with shifts and additions.
CLEANUP: hpack: be careful about integer promotion from uint8_t
As reported in issue #1635, there's a subtle sign change when shifting
a uint8_t value to the left because integer promotion first turns any
smaller type to signed int *even if it was unsigned*. A warning was
reported about uint8_t shifted left 24 bits that couldn't fit in int
due to this.
It was verified that the emitted code didn't change, as expected, but
at least this allows to silence the code checkers. There's no need to
backport this.
BUG/MINOR: h3: Missing wait event struct field initialization
This one has been detected by valgrind:
==2179331== Conditional jump or move depends on uninitialised value(s)
==2179331== at 0x1B6EDE: qcs_notify_recv (mux_quic.c:201)
==2179331== by 0x1A17C5: qc_handle_uni_strm_frm (xprt_quic.c:2254)
==2179331== by 0x1A1982: qc_handle_strm_frm (xprt_quic.c:2286)
==2179331== by 0x1A2CDB: qc_parse_pkt_frms (xprt_quic.c:2550)
==2179331== by 0x1A6068: qc_treat_rx_pkts (xprt_quic.c:3463)
==2179331== by 0x1A6C3D: quic_conn_app_io_cb (xprt_quic.c:3589)
==2179331== by 0x3AA566: run_tasks_from_lists (task.c:580)
==2179331== by 0x3AB197: process_runnable_tasks (task.c:883)
==2179331== by 0x357E56: run_poll_loop (haproxy.c:2750)
==2179331== by 0x358366: run_thread_poll_loop (haproxy.c:2921)
==2179331== by 0x3598D2: main (haproxy.c:3538)
==2179331==
This should be useful to have an idea of the list of frames which could be built
towards the list of available frames when building packets.
Same thing about the frames which could not be built because of a lack of room
in the TX buffer.
BUG/MINOR: quic: Do not probe from an already probing packet number space
During a handshake, after having prepared a probe upon a PTO expiration from
process_timer(), we wake up the I/O handler to make it send probing packets.
This handler first treat incoming packets which trigger a fast retransmission
leading to send too much probing (duplicated) packets. In this cas we cancel
the fast retranmission.
BUG/MINOR: quic: Discard Initial packet number space only one time
When discarding a packet number space, we at least reset the PTO backoff counter.
Doing this several times have an impact on the PTO duration calculation.
We must not discard a packet number space several times (this is already the case
for the handshake packet number space).
BUG/MINOR: quic: Missing probing packets when coalescing
Before having a look at the next encryption level to build packets if there is
no more ack-eliciting frames to send we must check we have not to probe from
the current encryption level anymore. If not, we only send one datagram instead
of sending two datagrams giving less chance to recover from packet loss.
Due to a erroneous interpretation of the RFC 9000 (quic-transport), ACKs frames
were always sent only after having received two ack-eliciting packets.
This could trigger useless retransmissions for tail packets on the peer side.
For now on, we send as soon as possible ACK frames as soon as we have ACK to send,
in the same packets as the ack-eliciting frame packets, and we also send ACK
frames after having received 2 ack-eliciting packets since the last time we sent
an ACK frame with other ack-eliciting frames.
CLEANUP: quic: Remove all atomic operations on packet number spaces
As such variables are handled by the QUIC connection I/O handler which runs
always on the thread, there is no need to continue to use such atomic operations
BUG/MEDIUM: quic: Possible crash in ha_quic_set_encryption_secrets()
This bug has come with this commit: 1fc5e16c4 MINOR: quic: More accurate immediately close
As mentionned in this commit we do not want to derive anymore secret when in closing
state. But the flag which denote secrets were derived was set. Add a label at
the correct flag to skip the secrets derivation without setting this flag.
Willy Tarreau [Thu, 31 Mar 2022 14:47:46 +0000 (16:47 +0200)]
BUG/MAJOR: mux_pt: always report the connection error to the conn_stream
Over time we've tried hard to abstract connection errors from the upper
layers so that they're reported per stream and not per connection. As
early as 1.8-rc1, commit 4ff3b8964 ("MINOR: connection: make conn_stream
users also check for per-stream error flag") did precisely this, but
strangely only for rx, not for tx (probably that by then send errors
were not imagined to be reported that way).
And this lack of Tx error check was just revealed in 2.6 by recent commit d1480cc8a ("BUG/MEDIUM: stream-int: do not rely on the connection error
once established") that causes wakeup loops between si_cs_send() failing
to send via mux_pt_snd_buf() and subscribing against si_cs_io_cb() in
loops because the function now rightfully only checks for CS_FL_ERROR
and not CO_FL_ERROR.
As found by Amaury, this causes aborted "show events -w" to cause
haproxy to loop at 100% CPU.
This fix theoretically needs to be backported to all versions, though
it will be necessary and sufficient to backport it wherever 4ff3b8964
gets backported.
Willy Tarreau [Thu, 31 Mar 2022 12:49:45 +0000 (14:49 +0200)]
BUG/MINOR: cli/stream: fix "shutdown session" to iterate over all threads
The list of streams was modified in 2.4 to become per-thread with commit a698eb673 ("MINOR: streams: use one list per stream instead of a global
one"). However the change applied to cli_parse_shutdown_session() is
wrong, as it uses the nullity of the stream pointer to continue on next
threads, but this one is not null once the list_for_each_entry() loop
is finished, it points to the list's head again, so the loop doesn't
check other threads, and no message is printed either to say that the
stream was not found.
Instead we should check if the stream is equal to the requested pointer
since this is the condition to break out of the loop.
Thus must be backported to 2.4. Thanks to Maciej Zdeb for reporting this.
Amaury Denoyelle [Tue, 29 Mar 2022 13:18:44 +0000 (15:18 +0200)]
MEDIUM: mux-quic: remove qcs tree node
The new qc_stream_desc type has a tree node for storage. Thus, we can
remove the node in the qcs structure.
When initializing a new stream, it is stored into the qcc streams_by_id
tree. When the MUX releases it, it will freed as soon as its buffer is
emptied. Before this, the quic-conn is responsible to store it inside
its own streams_by_id tree.
Amaury Denoyelle [Tue, 29 Mar 2022 13:15:54 +0000 (15:15 +0200)]
MEDIUM: quic: move transport fields from qcs to qc_conn_stream
Move the xprt-buf and ack related fields from qcs to the qc_stream_desc
structure. In exchange, qcs has a pointer to the low-level stream. For
each new qcs, a qc_stream_desc is automatically allocated.
This simplify the transport layer by removing qcs/mux manipulation
during ACK frame parsing. An additional check is done to not notify the
MUX on sending if the stream is already released : this case may now
happen on retransmission.
To complete this change, the quic_stream frame now references the
quic_stream instance instead of a qcs.
Amaury Denoyelle [Tue, 29 Mar 2022 12:49:35 +0000 (14:49 +0200)]
MINOR: quic: implement stream descriptor for transport layer
Currently, the mux qcs streams manage the Tx buffering, even after
sending it to the transport layer. Buffers are emptied when
acknowledgement are treated by the transport layer. This complicates the
MUX liberation and we may loose some data after the MUX free.
Change this paradigm by moving the buffering on the transport layer. For
this goal, a new type is implemented as low-level stream at the
transport layer, as a counterpart of qcs mux instances. This structure
is called qc_stream_desc. This will allow to free the qcs/qcc instances
without having to wait for acknowledge reception.
For the moment, the quic-conn is responsible to store the qc_stream_desc
in a new tree named streams_by_id. This will sligthly change in the next
commits to remove the qcs node which has a similar purpose :
qc_stream_desc instances will be shared between the qcc MUX and the
quic-conn.
This patch only introduces the new type definition and the function to
manipulate it. The following commit will bring the rearchitecture in the
qcs structure.
Amaury Denoyelle [Wed, 30 Mar 2022 09:51:56 +0000 (11:51 +0200)]
BUG/MINOR: mux-quic: ensure to free all qcs on MUX release
Remove qcs instances left during qcc MUX release. This can happen when
the MUX is closed before the completion of all the transfers, such as on
a timeout or process termination.
This may free some memory leaks on the connection.
Amaury Denoyelle [Tue, 29 Mar 2022 12:46:38 +0000 (14:46 +0200)]
MINOR: mux-quic: define release app-ops
Define a new callback release inside qcc_app_ops. It is called when the
qcc MUX is freed via qc_release. This will allows to implement cleaning
on the app layer.
Amaury Denoyelle [Tue, 29 Mar 2022 16:36:59 +0000 (18:36 +0200)]
MINOR: mux-quic: reorganize qcs free
Regroup some cleaning operations inside a new function qcs_free. This
can be used for all streams, both through qcs_destroy and with
uni-directional streams.
Amaury Denoyelle [Tue, 29 Mar 2022 09:51:17 +0000 (11:51 +0200)]
BUG/MEDIUM: quic: do not use qcs from quic_stream on ACK parsing
The quic_stream frame stores the qcs instance. On ACK parsing, qcs is
accessed to clear the stream buffer. This can cause a segfault if the
MUX or the qcs is already released.
Consider the following scenario :
1. a STREAM frame is generated by the MUX
transport layer emits the frame with PKN=1
upper layer has finished the transfer so related qcs is detached
2. transport layer reemits the frame with PKN=2 because ACK was not
received
3. ACK for PKN=1 is received, stream buffer is cleared
at this stage, qcs may be freed by the MUX as it is detached
4. ACK for PKN=2 is received
qcs for STREAM frame is dereferenced which will lead to a crash
To prevent this, qcs is never accessed from the quic_stream during ACK
parsing. Instead, a lookup is done on the MUX streams tree. If the MUX
is already released, no lookup is done. These checks prevents a possible
segfault.
This change may have an impact on the perf as now we are forced to use a
tree lookup operation. If this is the case, an alternative solution may
be to implement a refcount on qcs instances.
MINOR: ssl/lua: CertCache.set() allows to update an SSL certificate file
The CertCache.set() function allows to update an SSL certificate file
stored in the memory of the HAProxy process. This function does the same
as "set ssl cert" + "commit ssl cert" over the CLI.
This could be used to update the crt and key, as well as the OCSP, the
SCTL, and the OSCP issuer.
The implementation does yield every 10 ckch instances, the same way the
"commit ssl cert" do.
Willy Tarreau [Wed, 30 Mar 2022 10:12:44 +0000 (12:12 +0200)]
MINOR: services: alphabetically sort service names
Note that we cannot reuse dump_act_rules() because the output format
may be adjusted depending on the call place (this is also used from
haproxy -vv). The principle is the same however.
Willy Tarreau [Wed, 30 Mar 2022 10:08:00 +0000 (12:08 +0200)]
MINOR: filters: alphabetically sort the list of filter names
There are very few but they're registered from constructors, hence
in a random order. The scope had to be copied when retrieving the
next keyword. Note that this also has the effect of listing them
sorted in haproxy -vv.
Willy Tarreau [Wed, 30 Mar 2022 10:02:35 +0000 (12:02 +0200)]
MINOR: cli: alphanumerically sort the dump of supported commands
Like for previous keyword classes, we're sorting the output. But this
time as it's not trivial to do it with multiple words, instead we're
proceeding like the help command, we sort them on their usage message
when present, and fall back to the first word of the command when there
is no usage message (e.g. "help" command).
It's much more convenient to sort these keywords on output to detect
changes, and it's easy to do. The patch looks big but most of it is
only caused by an indent change in the loop, as "git diff -b" shows.
The output produced by dump_registered_keywords() really deserves to be
sorted in order to ease comparisons. The function now implements a tiny
sorting mechanism that's suitable for each two-level list, and makes
use of dump_act_rules() to dump rulesets. The code is not significantly
more complicated and some parts (e.g options) could even be factored.
The output is much more exploitable to detect differences now.
Willy Tarreau [Wed, 30 Mar 2022 09:19:22 +0000 (11:19 +0200)]
MINOR: action: add a function to dump the list of actions for a ruleset
The new function dump_act_rules() now dumps the list of actions supported
by a ruleset. These actions are alphanumerically sorted first so that the
produced output is easy to compare.
Willy Tarreau [Wed, 30 Mar 2022 08:02:56 +0000 (10:02 +0200)]
MINOR: tools: add strordered() to check whether strings are ordered
When trying to sort sets of strings, it's often needed to required to
compare 3 strings to see if the chosen one fits well between the two
others. That's what this function does, in addition to being able to
ignore extremities when they're NULL (typically for the first iteration
for example).
Willy Tarreau [Tue, 29 Mar 2022 14:59:49 +0000 (16:59 +0200)]
MINOR: sample: list registered sample converter functions
Similar to the sample fetch keywords, let's also list the converter
keywords. They're much simpler since there's no compatibility matrix.
Instead the input and output types are listed. This is called by
dump_registered_keywords() for the "cnv" keywords class.
Willy Tarreau [Tue, 29 Mar 2022 14:51:29 +0000 (16:51 +0200)]
MINOR: samples: add a function to list register sample fetch keywords
New function smp_dump_fetch_kw lists registered sample fetch keywords
with their compatibility matrix, mandatory and optional argument types,
and output types. It's called from dump_registered_keywords() with class
"smp".
Willy Tarreau [Tue, 29 Mar 2022 13:36:56 +0000 (15:36 +0200)]
MINOR: acl: add a function to dump the list of known ACL keywords
New function acl_dump_kwd() dumps the registered ACL keywords and their
sample-fetch equivalent to stdout. It's called by dump_registered_keywords()
for keyword class "acl".
Willy Tarreau [Tue, 29 Mar 2022 13:25:30 +0000 (15:25 +0200)]
MINOR: cli: add a new keyword dump function
New function cli_list_keywords() scans the list of registered CLI keywords
and dumps them on stdout. It's now called from dump_registered_keywords()
for the class "cli".
Some keywords are valid for the master, they'll be suffixed with
"[MASTER]". Others are valid for the worker, they'll have "[WORKER]".
Those accessible only in expert mode will show "[EXPERT]" and the
experimental ones will show "[EXPERIM]".
Willy Tarreau [Tue, 29 Mar 2022 13:10:44 +0000 (15:10 +0200)]
MINOR: services: extend list_services() to dump to stdout
When no output stream is passed, stdout is used with one entry per line,
and this is called from dump_registered_services() when passed the class
"svc".
Willy Tarreau [Tue, 29 Mar 2022 13:02:44 +0000 (15:02 +0200)]
MINOR: config: add a function to dump all known config keywords
All registered config keywords that are valid in the config parser are
dumped to stdout organized like the regular sections (global, listen,
etc). Some keywords that are known to only be valid in frontends or
backends will be suffixed with [FE] or [BE].
All regularly registered "bind" and "server" keywords are also dumped,
one per "bind" or "server" line. Those depending on ssl are listed after
the "ssl" keyword. Doing so required to export the listener and server
keyword lists that were static.
The function is called from dump_registered_keywords() for keyword
class "cfg".
Willy Tarreau [Tue, 8 Mar 2022 15:01:40 +0000 (16:01 +0100)]
MINOR: management: add some basic keyword dump infrastructure
It's difficult from outside haproxy to detect the supported keywords
and syntax. Interestingly, many of our modern keywords are enumerated
since they're registered from constructors, so it's not very hard to
enumerate most of them.
This patch creates some basic infrastructure to support dumping existing
keywords from different classes on stdout. The format will differ depending
on the classes, but the idea is that the output could easily be passed to
a script that generates some simple syntax highlighting rules, completion
rules for editors, syntax checkers or config parsers.
The principle chosen here is that if "-dK" is passed on the command-line,
at the end of the parsing the registered keywords will be dumped for the
requested classes passed after "-dK". Special name "help" will show known
classes, while "all" will execute all of them. The reason for doing that
after the end of the config processor is that it will also enumerate
internally-generated keywords, Lua or even those loaded from external
code (e.g. if an add-on is loaded using LD_PRELOAD). A typical way to
call this with a valid config would be:
./haproxy -dKall -q -c -f /path/to/config
If there's no config available, feeding /dev/null will also do the job,
though it will not be able to detect dynamically created keywords, of
course.
This patch also updates the management doc.
For now nothing but the help is listed, various subsystems will follow
in subsequent patches.
Willy Tarreau [Tue, 29 Mar 2022 14:39:24 +0000 (16:39 +0200)]
BUG/MINOR: samples: add missing context names for sample fetch functions
In 2.4, two commits added support for supporting sample fetch calls from
new config and CLI contexts, but these were not added to the visibile
names, which may possibly cause "(null)" to appear in some error messages.
The commit in question were: db5e0dbea ("MINOR: sample: add a new CLI_PARSER context for samples") f9a7a8fd8 ("MINOR: sample: add a new CFG_PARSER context for samples")
This patch needs to be backported where these are present (2.4 and above).
BUG/MINOR: log: Initialize the list element when allocating a new log server
211ea252d ("BUG/MINOR: logs: fix logsrv leaks on clean exit") introduced a
regression because the list element of a new log server is not intialized. Thus
HAProxy crashes on error path when an invalid log server is released.
This patch shoud fix the issue #1636. It must be backported if the above commit
is backported. For now, it is 2.6-specific and no backport is needed.
BUG/MEDIUM: mux-h1: Properly detect full buffer cases during message parsing
When the destination buffer is full while there are still data to parse, the
h1s must be marked as congested to be able to restart the parsing
later. This work on headers and data parsing. But on trailers parsing, we
fail to do so when the buffer is full before to parse the trailers. In this
case, we skip the trailers parsing but the h1s is not marked as
congested. This is important to be sure to wake up the mux to restart the
parsing when some room is made in the buffer.
Because of this bug, the message processing may hang till a timeout is
triggered. Note that for 2.3 and 2.2, the EOM processing is buggy too, for
the same reason. It should be fixed too on these versions. On the 2.0, only
trailers parsing is affected.
This patch must be backported as far as 2.0. On 2.3 and 2.2, the EOM parsing
must be fixed too.
BUG/MEDIUM: mux-fcgi: Properly handle return value of headers/trailers parsing
h1_parse_msg_hdrs() and h1_parse_msg_tlrs() may return negative values if
the parsing fails or if more space is needed in the destination buffer. When
h1-htx was changed, The H1 mux was updated accordingly but not the FCGI
mux. Thus if a negative value is returned, it is ignored and it is casted to
a size_t, leading to an integer overflow on the <ofs> value, used to know
the position in the RX buffer.
Lukas Tribus [Sat, 26 Mar 2022 19:43:48 +0000 (20:43 +0100)]
DOC: reflect H2 timeout changes
Reverts 75df9d7a7 ("DOC: explain HTTP2 timeout behavior") since H2
connections now respect "timeout http-keep-alive".
If commit 15a4733d5d ("BUG/MEDIUM: mux-h2: make use of http-request
and keep-alive timeouts") is backported, this DOC change needs to
be backported along with it.
Willy Tarreau [Sat, 26 Mar 2022 07:31:33 +0000 (08:31 +0100)]
[RELEASE] Released version 2.6-dev4
Released version 2.6-dev4 with the following main changes :
- BUG/MEDIUM: httpclient: don't consume data before it was analyzed
- CLEANUP: htx: remove unused co_htx_remove_blk()
- BUG/MINOR: httpclient: consume partly the blocks when necessary
- BUG/MINOR: httpclient: remove the UNUSED block when parsing headers
- BUG/MEDIUM: httpclient: must manipulate head, not first
- REGTESTS: fix the race conditions in be2hex.vtc
- BUG/MEDIUM: quic: Blocked STREAM when retransmitted
- BUG/MAJOR: quic: Possible crash with full congestion control window
- BUG/MINOR: httpclient/lua: stuck when closing without data
- BUG/MEDIUM: applet: Don't call .release callback function twice
- BUG/MEDIUM: cli/debug: Properly get the stream-int in all debug I/O handlers
- BUG/MEDIUM: sink: Properly get the stream-int in appctx callback functions
- DEV: udp: switch parser to getopt() instead of positional arguments
- DEV: udp: add support for random packet corruption
- MINOR: server: export server_parse_sni_expr() function
- BUG/MINOR: httpclient: send the SNI using the host header
- BUILD: httpclient: fix build without SSL
- BUG/MINOR: server/ssl: free the SNI sample expression
- BUG/MINOR: logs: fix logsrv leaks on clean exit
- MINOR: actions: add new function free_act_rule() to free a single rule
- BUG/MINOR: tcp-rules: completely free incorrect TCP rules on error
- BUG/MINOR: http-rules: completely free incorrect TCP rules on error
- BUG/MINOR: httpclient: only check co_data() instead of HTTP_MSG_DATA
- BUG/MINOR: httpclient: process the response when received before the end of the request
- BUG/MINOR: httpclient: CF_SHUTW_NOW should be tested with channel_is_empty()
- CI: github actions: switch to LibreSSL-3.5.1
- BUG/MEDIUM: mux-h1: only turn CO_FL_ERROR to CS_FL_ERROR with empty ibuf
- BUG/MEDIUM: stream-int: do not rely on the connection error once established
- BUG/MEDIUM: trace: avoid race condition when retrieving session from conn->owner
- MEDIUM: mux-h2: slightly relax timeout management rules
- BUG/MEDIUM: mux-h2: make use of http-request and keep-alive timeouts
- BUG/MINOR: rules: Initialize the list element when allocating a new rule
- BUG/MINOR: http-rules: Don't free new rule on allocation failure
- DEV: coccinelle: Fix incorrect replacement in ist.cocci
- CLEANUP: Reapply ist.cocci with `--include-headers-for-types --recursive-includes`
- DEV: coccinelle: Add a new pattern to ist.cocci
- CLEANUP: Reapply ist.cocci
- REGTESTS: Do not use REQUIRE_VERSION for HAProxy 2.5+
- MINOR: quic: Code factorization (TX buffer reuse)
- CLEANUP: quic: "largest_acked_pn" pktns struc member moving
- MEDIUM: quic: Limit the number of ACK ranges
- MEDIUM: quic: Rework of the TX packets memory handling
- BUG/MINOR: quic: Possible crash in parse_retry_token()
- BUG/MINOR: quic: Possible leak in quic_build_post_handshake_frames()
- BUG/MINOR: quic: Unsent frame because of qc_build_frms()
- BUG/MINOR: mux-quic: Access to empty frame list from qc_send_frames()
- BUG/MINOR: mux-quic: Missing I/O handler events initialization
- BUG/MINOR: quic: Missing TX packet initializations
- BUG/MINOR: quic: 1RTT packets ignored after mux was released
- BUG/MINOR: quic: Incorrect peer address validation
- BUG/MINOR: quic: Non initialized variable in quic_build_post_handshake_frames()
- BUG/MINOR: quic: Wrong TX packet related counters handling
- MEDIUM: mqtt: support mqtt_is_valid and mqtt_field_value converters for MQTTv3.1
- DOC: config: Explictly add supported MQTT versions
- MINOR: quic: Add traces about stream TX buffer consumption
- MINOR: quic: Add traces in qc_set_timer() (scheduling)
- CLEANUP: mux-quic: change comment style to not mess with git conflict
- CLEANUP: mux-quic: adjust comment for coding-style
- MINOR: mux-quic: complete trace when stream is not found
- MINOR: mux-quic: add comments for send functions
- MINOR: mux-quic: use shorter name for flow-control fields
- MEDIUM: mux-quic: respect peer bidirectional stream data limit
- MEDIUM: mux-quic: respect peer connection data limit
- MINOR: mux-quic: support MAX_STREAM_DATA frame parsing
- MINOR: mux-quic: support MAX_DATA frame parsing
- BUILD: stream-int: avoid a build warning when DEBUG is empty
- BUG/MINOR: quic: Wrong buffer length passed to generate_retry_token()
- BUG/MINOR: tools: fix url2sa return value with IPv4
- MINOR: mux-quic: convert fin on push-frame as boolean
- BUILD: quic: add missing includes
- REORG: quic: use a dedicated quic_loss.c
- MINOR: mux-quic: declare the qmux trace module
- MINOR: mux-quic: replace printfs by traces
- MINOR: mux-quic: add trace event for frame sending
- MINOR: mux-quic: add trace event for qcs_push_frame
- MINOR: mux-quic: activate qmux traces on stdout via macro
- BUILD: qpack: fix unused value when not using DEBUG_HPACK
- CLEANUP: qpack: suppress by default stdout traces
- CLEANUP: h3: suppress by default stdout traces
- BUG/MINOR: tools: url2sa reads too far when no port nor path
BUG/MINOR: tools: url2sa reads too far when no port nor path
url2sa() still have an unfortunate case where it reads 1 byte too far,
it happens when no port or path are specified in the URL, and could
crash if the byte after the URL is not allocated (mostly with ASAN).
This case is never triggered in old versions of haproxy because url2sa
is used with buffers which are way bigger than the URL. It is only
triggered with the httpclient.
Amaury Denoyelle [Fri, 25 Mar 2022 13:56:51 +0000 (14:56 +0100)]
CLEANUP: qpack: suppress by default stdout traces
Remove the definition of DEBUG_HPACK on qpack-dec.c which forces the
QPACK decoding traces on stderr. Also change the name to use a dedicated
one for QPACK decoding as DEBUG_QPACK.
If the macro ENABLE_QUIC_STDOUT_TRACES is defined, qmux traces are
outputted automatically on stdout. This is useful for the haproxy-qns
interop docker image.
Amaury Denoyelle [Fri, 25 Mar 2022 08:09:40 +0000 (09:09 +0100)]
MINOR: mux-quic: add trace event for frame sending
Define a new qmux event QMUX_EV_SEND_FRM. This allows to pass a
quic_frame as an extra argument. Depending on the frame type, a special
format can be used to log the frame content.
Currently this event is only used in qc_send_max_streams. Thus the
handler is only able to handle MAX_STREAMS frames.
Amaury Denoyelle [Thu, 24 Mar 2022 16:10:00 +0000 (17:10 +0100)]
MINOR: mux-quic: replace printfs by traces
Convert all printfs in the mux-quic code with traces.
Note that some meaningul printfs were not converted because they use
extra args in a format-string. This is the case inside qcs_push_frame
and qc_send_max_streams. A dedicated trace event should be implemented
for them to be able to display the extra arguments.