Commit Graph

12588 Commits

Author SHA1 Message Date
Amaury Denoyelle
725f8d29ff MINOR: server: enable more check related keywords for dynamic servers
Allow to use the check related keywords defined in server.c. These
keywords can be enabled now that checks have been implemented for
dynamic servers.

Here is the list of the new keywords supported :
- error-limit
- observe
- on-error
- on-marked-down
- on-marked-up
2021-09-21 14:00:32 +02:00
Amaury Denoyelle
79b90e8cd4 MINOR: server: enable more keywords for ssl checks for dynamic servers
Allow to configure ssl support for dynamic server checks independently
of the ssl server configuration. This is done via the keyword
"check-ssl". Also enable to configure the sni/alpn used for the check
via "check-sni/alpn".
2021-09-21 14:00:07 +02:00
Amaury Denoyelle
b621552ca3 BUG/MINOR: server: alloc dynamic srv ssl ctx if proxy uses ssl chk rule
The ssl context is not initialized for a dynamic server, even if there
is a tcpcheck rule which uses ssl on the related backed. This will cause
the check initialization to failed with the message :
  "Out of memory when initializing an SSL connection"

This can be reproduced by having the following config in the backend :
  option tcp-check
  tcp-check connect ssl
and create a dynamic server with check activated and a ca-file.

Fix this by calling the prepare_srv xprt callback when the proxy options
PR_O_TCPCKH_SSL is set.

Check support for dynamic servers has been merged in the current branch.
No backport needed.
2021-09-21 13:56:03 +02:00
Amaury Denoyelle
0f456d5029 BUG/MINOR: server: allow 'enable health' only if check configured
Test that checks have been configured on the server before enabling via
the 'enable health' CLI. This mirrors the 'enable agent' command.

Without this, a user can use the command on the server without checks.
This leaves the server in an undefined state. Notably, the stat page
reports the server in check transition.

This condition was left on the following reorg commit.
  2c04eda8b5
  REORG: cli: move "{enable|disable} health" to server.c

This should be backported up to 1.8.
2021-09-21 11:50:22 +02:00
Tim Duesterhus
4f065262e9 CLEANUP: Remove unreachable break from parse_time_err()
The `return` already leaves the function.
2021-09-20 18:37:32 +02:00
Tim Duesterhus
75e2f8dcdd CLEANUP: Include check.h in flt_spoe.c
This is required for the prototype of spoe_prepare_healthcheck_request().
2021-09-20 18:37:32 +02:00
William Lallemand
79a3478c24 MINOR: httpclient: add the EOH when no headers where provided
httpclient_req_gen() now adds the end of headers block when no header
was provided, which avoid adding it manually.
2021-09-20 16:24:54 +02:00
Dragan Dosen
a8018eb470 BUG/MINOR: flt-trace: fix an infinite loop when random-parsing is set
The issue is introduced with the commit c41d8bd65 ("CLEANUP: flt-trace:
Remove unused random-parsing option").

This must be backported everywhere the above commit is.
2021-09-20 16:06:58 +02:00
Tim Duesterhus
ec4a8754da CLEANUP: Apply xalloc_size.cocci
This fixes a few locations with a hardcoded type within `sizeof()`.
2021-09-17 17:22:05 +02:00
Tim Duesterhus
16554245e2 CLEANUP: Apply bug_on.cocci
The changes look safe to me, even if `DEBUG_STRICT` is not enabled.
2021-09-17 17:22:05 +02:00
Tim Duesterhus
b113b5ca24 CLEANUP: Apply ist.cocci
This cleans up ist handling.
2021-09-17 17:22:05 +02:00
Willy Tarreau
e61244631a MINOR: applet: remove the thread mask from appctx_new()
appctx_new() is exclusively called with tid_bit and it only uses the
mask to pass it to the accompanying task. There is no point requiring
the caller to know about a mask there, nor is there any point in
creating an applet outside of the context of its own thread anyway.
Let's drop this and pass tid_bit to task_new() directly.
2021-09-17 16:08:34 +02:00
Willy Tarreau
87063a7da1 BUILD: fd: remove unused variable totlen in fd_write_frag_line()
Ilya reports in GH #1392 that clang 13 complains about totlen being
calculated and not used in fd_write_frag_line(), which is true. It's
a leftover of some older code.
2021-09-17 12:00:27 +02:00
Willy Tarreau
b5d1141305 BUILD: proto_uxst: do not set unused flag
Similarly to previous patch for sockpair, UNIX sockets set the
CONNECT_HAS_DATA flag without using it later, we can drop it.
2021-09-17 11:59:15 +02:00
Willy Tarreau
0ce77ac204 BUILD: sockpair: do not set unused flag
Ilya reports in GH #1392 that clang 13 complains about a flag being added
to the "flags" parameter without being used later. That's generic code
that was shared from TCP but we can indeed drop this flag since it's used
for TFO which we don't have in socketpairs.
2021-09-17 11:56:25 +02:00
Willy Tarreau
f2dda52e78 BUG/MINOR: cli/payload: do not search for args inside payload
The CLI's payload parser is over-complicated and as such contains more
bugs than needed. One of them is that it uses strstr() to find the
ending tag, ignoring spaces before it, while the argument locator
creates a new arg on each space, without checking if the end of the
word appears past the previously found end. This results in "<<" being
considered as the start of a new argument if preceeded by more than
one space, and the payload being damaged with a \0 inserted at the
first space or tab.

Let's make an easily backportable fix for now. This fix makes sure that
the trailing zero from the first line is properly kept after '<<' and
that the end tag is looked for only as an isolated argument and nothing
else. This also gets rid of the unsuitable strstr() call and now makes
sure that strcspn() will not return elements that are found in the
payload.

For the long term the loop must be rewritten to get rid of those
unsuitable strcspn() and strstr() calls which work past each other, and
the cli_parse_request() function should be split into a tokenizer and
an executor that are used from the caller instead of letting the caller
play games with what it finds there.

This should be backported wherever CLI payload is supported, i.e. 2.0+.
2021-09-17 11:50:09 +02:00
Amaury Denoyelle
4837293ca0 BUG/MINOR: connection: prevent null deref on mux cleanup task allocation
Move the code to allocate/free the mux cleanup task outside of the polling
loop. A new thread_alloc/free handler is registered for this in
connection.c.

This has the benefit to clean up the polling loop code. And as another
benefit, if the task allocation fails, the handler can report an error
to exit the haproxy process. This prevents a potential null pointer
dereferencing.

This should fix the github issue #1389.

This must be backported up to 2.4.
2021-09-16 17:45:52 +02:00
Christopher Faulet
8a0e5f822b BUG/MINOR: tcpcheck: Improve LDAP response parsing to fix LDAP check
When the LDAP response is parsed, the message length is not properly
decoded. While it works for LDAP servers encoding it on 1 byte, it does not
work for those using a multi-bytes encoding. Among others, Active Directory
servers seems to encode messages or elements length on 4 bytes.

In this patch, we only handle length of BindResponse messages encoded on 1,
2 or 4 bytes. In theory, it may be encoded on any bytes number less than 127
bytes. But it is useless to make this part too complex. It should be ok this
way.

This patch should fix the issue #1390. It should be backported to all stable
versions. While it should be easy to backport it as far as 2.2, the patch
will have to be totally rewritten for lower versions.
2021-09-16 17:24:50 +02:00
Willy Tarreau
c2afb860f2 MINOR: pools: use mallinfo2() when available instead of mallinfo()
Ilya reported in issue #1391 a build warning on Fedora about mallinfo()
being deprecated in favor of mallinfo2() since glibc-2.33. Let's add
support for it. This should be backported where the following commit is
also backported: 157e39303 ("MINOR: pools: automatically disable
malloc_trim() with external allocators").
2021-09-16 09:20:16 +02:00
Christopher Faulet
ab7389dc3c BUG/MAJOR: mux-h1: Don't eval input data if an error was reported
If an error was already reported on the H1 connection, pending input data
must not be (re)evaluated in h1_process(). Otherwise an unexpected internal
error will be reported, in addition of the first one. And on some
conditions, this may generate an infinite loop because the mux tries to send
an internal error but it fails to do so thus it loops to retry.

This patch should fix the issue #1356. It must be backported to 2.4.
2021-09-16 08:31:46 +02:00
Christopher Faulet
51324b8720 CLEANUP: acl: Remove unused variable when releasing an acl expression
The "unresolved" variable is unused since commit 9fa0df5 ("BUG/MINOR: acl:
Fix freeing of expr->smp in prune_acl_expr").

This patch should fix the issue #1359.
2021-09-16 08:31:46 +02:00
Willy Tarreau
845b560f6a MINOR: pools: report it when malloc_trim() is enabled
Since we can detect it at runtime now, it could help to have it mentioned
in haproxy -vv.
2021-09-15 10:41:24 +02:00
Willy Tarreau
157e393039 MINOR: pools: automatically disable malloc_trim() with external allocators
Pierre Cheynier reported some occasional crashes in malloc_trim() on a
recent glibc when running with jemalloc(). While in theory there should
not be any link between the two, it remains plausible that something
allocated early with one is tentatively freed with the other and that
attempts to trim end up badly. There's no point calling the glibc specific
malloc_trim() with external allocators anyway. However these ones are often
enabled at link time or even at run time with LD_PRELOAD, so we cannot rely
on build options for this.

This patch implements runtime detection for the allocator in use by checking
with mallinfo() that a malloc() call is properly accounted for in glibc's
malloc. It only enables malloc_trim() in this case, and ignores it for
other cases. It's fine to proceed like this because mallinfo() is provided
by a wider range of glibcs than malloc_trim().

This could be backported to 2.4 and 2.3. If so, it will also need previous
patch "CLEANUP: pools: factor all malloc_trim() calls into trim_all_pools()".
2021-09-15 10:40:39 +02:00
Willy Tarreau
ea3323f62c CLEANUP: pools: factor all malloc_trim() calls into trim_all_pools()
The code was slightly cleaned up by removing repeated occurrences of ifdefs
and moving that into a single trim_all_pools() function.
2021-09-15 10:38:21 +02:00
Willy Tarreau
c5d0fc9b9f BUILD: sample: fix format warning on 32-bit archs in sample_conv_be2dec_check()
The sizeof() was printed as a long but it's just an unsigned on some
32-bit platforms, hence the format warning. No backport is needed, as
this arrived in 2.5 with commit  40ca09c7b ("MINOR: sample: Add be2dec
converter").
2021-09-15 10:32:12 +02:00
Tim Duesterhus
2281738256 BUG/MEDIUM lua: Add missing call to RESET_SAFE_LJMP in hlua_filter_new()
In one case before exiting leaving the function the panic handler was not
reset.

Introduced in 69c581a092, which is 2.5+.
No backport required.
2021-09-12 08:21:07 +02:00
Tim Duesterhus
d5fc8fcb86 CLEANUP: Add haproxy/xxhash.h to avoid modifying import/xxhash.h
This solves setting XXH_INLINE_ALL in a cleaner way, because the imported
header is not modified, easing future updates.

see 6f7cc11e6d
2021-09-11 19:58:45 +02:00
Christopher Faulet
949b6ca961 BUG/MINOR: filters: Set right FLT_END analyser depending on channel
A bug was introduced by the commit 26eb5ea35 ("BUG/MINOR: filters: Always
set FLT_END analyser when CF_FLT_ANALYZE flag is set"). Depending on the
channel evaluated, the rigth FLT_END analyser must be set. AN_REQ_FLT_END
for the request channel and AN_RES_FLT_END for the response one.

Ths patch must be backported everywhere the above commit was backported.
2021-09-10 10:35:53 +02:00
Christopher Faulet
2d56500826 BUG/MEDIUM: http-ana: Reset channels analysers when returning an error
When an error is returned to the client, via a call to
http_reply_and_close(), the request channel is flushed and shut down and
HTTP analysis on both direction is finished. So it is safer to centralize
reset of channels analysers at this place. It is especially important when a
filter is attached to the stream when a client abort is detected. Because,
otherwise, the stream remains blocked because request analysers are not
reset.

This bug was hidden for a while. But since the fix 6fcd2d328 ("BUG/MINOR:
stream: Don't release a stream if FLT_END is still registered"), it is
possible to trigger it.

This patch must be backported everywhere the above commit was backported.
2021-09-10 10:35:53 +02:00
Christopher Faulet
883d83e83c BUG/MEDIUM: stream-int: Don't block SI on a channel policy if EOI is reached
If the end of input is reported by the mux on the conn-stream during a
receive, we leave without evaluating the channel policies. It is especially
important to be able to catch client aborts during server connection
establishment. Indeed, in this case, without this patch, the
stream-interface remains blocked and read events are not forwarded to the
stream. It means it is not possible to detect client aborts.

Thanks to this fix, the abortonclose option should fixed for HAProxy 2.3 and
lower. On 2.4 and 2.5, it seems to work because the stream is created after
the request parsing.

Note that a previous fix of abortonclose option was reverted. This one
should be the right way to fix it. It must carefully be backported as far as
2.0. A observation period on the 2.3 is probably a good idea.
2021-09-10 10:35:53 +02:00
Christopher Faulet
0fa8007102 CLEANUP: mux-h1: Remove condition rejecting upgrade requests with payload
Now, "Upgrade:" header is removed from such requests. Thus, the condition to
reject them is now useless and can be removed. Code to handle unimplemented
features is now unused but is preserved for future uses.

This patch may be backported to 2.4.
2021-09-10 10:35:53 +02:00
Christopher Faulet
52a5ec2d18 BUG/MEDIUM: mux-h1: Remove "Upgrade:" header for requests with payload
Instead of returning a 501-Not-implemented error when "Ugrade:" header is
found for a request with a payload, the header is removed. This way, the
upgrade is disabled and the request is still sent to the server. It is
required because some frameworks seem to try to perform H2 upgrade on every
requests, including POST ones.

The h2 mux was slightly fixed to convert Upgrade requests to extended
connect ones only if the rigth HTX flag is set.

This patch should fix the issue #1381. It must be backported to 2.4.
2021-09-10 09:17:51 +02:00
Willy Tarreau
55f8a830dc OPTIM: vars: do not keep variables usage stats if no limit is set
The sole purpose of the variable's usage accounting is to enforce
limits at the session or process level, but very commonly these are not
set, yet the bookkeeping (especially at the process level) is extremely
expensive.

Let's simply disable it when the limits are not set. This further
increases the performance of 12 variables on 16-thread from 1.06M
to 1.24M req/s.
2021-09-08 15:53:07 +02:00
Willy Tarreau
3b78f2aa5d OPTIM: vars: remove internal bookkeeping for vars_global_size
Right now we have a per-process max variable size and a per-scope one,
with the proc scope covering all others. As such, the per-process global
one is always exactly equal to the per-proc-scope one. And bookkeeping
on these process-wide variables is extremely expensive (up to 38% CPU
seen in var_accounting_diff() just for them).

Let's kill vars_global_size and only rely on the proc one. Doing this
increased the request rate from 770k to 1.06M in a config having only
12 variables on a 16-thread machine.
2021-09-08 15:45:05 +02:00
Willy Tarreau
dc72fbb8e8 MINOR: vars: centralize the lock/unlock into static inlines
The goal it to simplify the variables locking in order to later
simplify it.
2021-09-08 15:19:57 +02:00
Willy Tarreau
3f120d2a58 CLEANUP: vars: remove the now unused var_names array
This was the table of all variable names known to the haproxy process.
It's not used anymore.
2021-09-08 15:09:22 +02:00
Willy Tarreau
3a4bedccc6 MEDIUM: vars: replace the global name index with a hash
The global table of known variables names can only grow and was designed
for static names that are registered at boot. Nowadays it's possible to
set dynamic variable names from Lua or from the CLI, which causes a real
problem that was partially addressed in 2.2 with commit 4e172c93f
("MEDIUM: lua: Add `ifexist` parameter to `set_var`"). Please see github
issue #624 for more context.

This patch simplifies all this by removing the need for a central
registry of known names, and storing 64-bit hashes instead. This is
highly sufficient given the low number of variables in each context.
The hash is calculated using XXH64() which is bijective over the 64-bit
space thus is guaranteed collision-free for 1..8 chars. Above that the
risk remains around 1/2^64 per extra 8 chars so in practice this is
highly sufficient for our usage. A random seed is used at boot to seed
the hash so that it's not attackable from Lua for example.

There's one particular nit though. The "ifexist" hack mentioned above
is now limited to variables of scope "proc" only, and will only match
variables that were already created or declared, but will now verify
the scope as well. This may affect some bogus Lua scripts and SPOE
agents which used to accidentally work because a similarly named
variable used to exist in a different scope. These ones may need to be
fixed to comply with the doc.

Now we can sum up the situation as this one:
  - ephemeral variables (scopes sess, txn, req, res) will always be
    usable, regardless of any prior declaration. This effectively
    addresses the most problematic change from the commit above that
    in order to work well could have required some script auditing ;

  - process-wide variables (scope proc) that are mentioned in the
    configuration, referenced in a "register-var-names" SPOE directive,
    or created via "set-var" in the global section or the CLI, are
    permanent and will always accept to be set, with or without the
    "ifexist" restriction (SPOE uses this internally as well).

  - process-wide variables (scope proc) that are only created via a
    set-var() tcp/http action, via Lua's set_var() calls, or via an
    SPOE with the "force-set-var" directive), will not be permanent
    but will always accept to be replaced once they are created, even
    if "ifexist" is present

  - process-wide variables (scope proc) that do not exist will only
    support being created via the set-var() tcp/http action, Lua's
    set_var() calls without "ifexist", or an SPOE declared with
    "force-set-var".

This means that non-proc variables do not care about "ifexist" nor
prior declaration, and that using "ifexist" should most often be
reliable in Lua and that SPOE should most often work without any
prior declaration. It may be doable to turn "ifexist" to 1 by default
in Lua to further ease the transition. Note: regtests were adjusted.

Cc: Tim Dsterhus <tim@bastelstu.be>
2021-09-08 15:06:11 +02:00
Willy Tarreau
2c897d9d1b MINOR: vars: preset a random seed to hash variables names
Variables names will be hashed, but for this we need a random seed.
The XXH3() algorithms is bijective over the whole 64-bit space, which
is great as it guarantees no collision for 1..8 byte names. But above
that even if the risk is extremely faint, it theoretically exists and
since variables may be set from Lua we'd rather do our best to limit
the risk of controlled collision, hence the random seed.
2021-09-08 15:06:11 +02:00
Willy Tarreau
df8eeb1619 MEDIUM: vars: pre-create parsed SCOPE_PROC variables as permanent ones
All variables whose names are parsed by the config parser, the
command-line parser or the SPOE's register-var-names parser are
now preset as permanent. This will guarantee that these variables
will exist through out all the process' life, and that it will be
possible to implement the "ifexist" feature by looking them up.

This was marked medium because pre-setting a variable with an empty
value may always have side effects, even though none was spotted at
this stage.
2021-09-08 15:06:11 +02:00
Willy Tarreau
c1c88f4809 MEDIUM: vars: make var_clear() only reset VF_PERMANENT variables
We certainly do not want that a permanent variable (one that is listed
in the configuration) be erased by accident by an "unset-var" action.
Let's make sure these ones are only reset to an empty sample, like at
the moment of their initial registration. One trick is that the same
function is used to purge the memory at the end and to delete, so we
need to add an extra "force" argument to make the choice.
2021-09-08 15:06:11 +02:00
Willy Tarreau
3dc6dc3178 MINOR: vars: store flags into variables and add VF_PERMANENT
In order to continue to honor the ifexist Lua option and prevent rogue
SPOA agents from creating too many variables, we'll need to keep the
ability to mark certain proc.* variables as permanent when they're
known from the config file.

Let's add a flag there for this. It's added to the variable when the
variable is created with this flag set by the caller.

Another approach could have been to use a distinct list or distinct
scope but that sounds complicated and bug-prone.
2021-09-08 14:06:34 +02:00
Willy Tarreau
63c30667d7 MINOR: vars: support storing empty sample data with a variable
Storing an unset sample (SMP_T_ANY == 0) will be used to only reserve
the variable's space but associate no value. We need to slightly adjust
var_to_smp() for this so that it considers a value-less variable as non
existent and falls back to the default value.
2021-09-08 13:59:43 +02:00
Willy Tarreau
4994b57728 MINOR: vars: add a VF_CREATEONLY flag for creation
Passing this flag to var_set() will result in the variable to only be
created if it did not exist, otherwise nothing is done (it's not even
updated). This will be used for pre-registering names.
2021-09-08 11:47:30 +02:00
Willy Tarreau
7978c5c422 MEDIUM: vars: make the ifexist variant of set-var only apply to the proc scope
When setting variables, there are currently two variants, one which will
always create the variable, and another one, "ifexist", which will only
create or update a variable if a similarly named variable in any scope
already existed before.

The goal was to limit the risk of injecting random names in the proc
scope, but it was achieved by making use of the somewhat limited name
indexing model, which explains the scope-agnostic restriction.

With this change, we're moving the check downwards in the chain, at the
variable level, and only variables under the scope "proc" will be subject
to the restriction. A new set of VF_* flags was added to adjust how
variables are set, and VF_UPDATEONLY is used to mention this restriction.

In this exact state of affairs, this is not completely exact, as if a
similar name was not known in any scope, the variable will continue to
be rejected like before, but this will change soon.
2021-09-08 11:47:06 +02:00
Willy Tarreau
f1cb0ebe3e REORG: vars: remerge sample_store{,_stream}() into var_set()
The names for these two functions are totally misleading, they have
nothing to do with samples, they're purely dedicated to variables. The
former is only used by the second one and makes no sense by itself, so
it cannot even get a meaningful name. Let's remerge them into a single
one called "var_set()" which, as its name tries to imply, sets a variable
to a given value.
2021-09-08 11:10:16 +02:00
Willy Tarreau
d378eb82d9 CLEANUP: vars: rename sample_clear_stream() to var_unset()
This name was quite misleading, as it has nothing to do with samples nor
streams. This function's sole purpose is to unset a variable, so let's
call it "var_unset()" and document it a little bit.
2021-09-08 11:10:16 +02:00
Willy Tarreau
b7bfcb3ff3 MINOR: vars: rename vars_init() to vars_init_head()
The vars_init() name is particularly confusing as it does not initialize
the variables code but the head of a list of variables passed in
arguments. And we'll soon need to have proper initialization code, so
let's rename it now.
2021-09-08 11:10:16 +02:00
Willy Tarreau
10080716bf MINOR: proxy: add a global "grace" directive to postpone soft-stop
In ticket #1348 some users expressed some concerns regarding the removal
of the "grace" directive from the proxies. Their use case very closely
mimmicks the original intent of the grace keyword, which is, let haproxy
accept traffic for some time when stopping, while indicating an external
LB that it's stopping.

This is implemented here by starting a task whose expiration triggers
the soft-stop for real. The global "stopping" variable is immediately
set however. For example, this below will be sufficient to instantly
notify an external check on port 9999 that the service is going down,
while other services remain active for 10s:

    global
      grace 10s

    frontend ext-check
      bind :9999
      monitor-uri /ext-check
      monitor fail if { stopping }
2021-09-07 17:34:29 +02:00
Christopher Faulet
b7308f00cb Revert "BUG/MINOR: stream-int: Don't block reads in si_update_rx() if chn may receive"
This reverts commit e0dec4b7b2.

At first glance, channel_is_empty() was used on purpose in si_update_rx(),
because of the HTX ("b3e0de46c" MEDIUM: stream-int: Rely only on
SI_FL_WAIT_ROOM to stop data receipt). It is not pretty clear for now why
channel_may_recv() sould not be used here but this change introduce a
possible infinite loop with the stats applet. So, it is safer to revert the
patch, waiting for a better understanding of the probelm.

This means the abortonclose option will be broken again on the 2.3 and lower
versions.

This patch should fix the issue #1360. It must be backported as far as 2.0.
2021-09-07 14:31:02 +02:00
Willy Tarreau
3d5f19e04d CLEANUP: htx: remove comments about "must be < 256 MB"
Since commit "BUG/MINOR: config: reject configs using HTTP with bufsize
>= 256 MB" we are now sure that it's not possible anymore to have an HTX
block of a size 256 MB or more, even after concatenation thanks to the
tests for len >= htx_free_data_space(). Let's remove these now obsolete
comments.

A BUG_ON() was added in htx_add_blk() to track any such exception if
the conditions would change later, to complete the one that is performed
on the start address that must remain within the buffer.
2021-09-03 16:15:29 +02:00
Willy Tarreau
32b51cdf30 BUG/MINOR: config: reject configs using HTTP with bufsize >= 256 MB
As seen in commit 5ef965606 ("BUG/MINOR: lua: use strlcpy2() not
strncpy() to copy sample keywords"), configs with large values of
tune.bufsize were not practically usable since Lua was introduced,
regardless of the machine's available memory.

In addition, HTX encoding already limits block sizes to 256 MB, thus
it is not technically possible to use that large a buffer size when
HTTP is in use. This is absurdly high anyway, and for example Lua
initialization would take around one minute on a 4 GHz CPU. Better
prevent such a config from starting than having to deal with bug
reports that make no sense.

The check is only enforced if at least one HTX proxy was found, as
there is no techincal reason to block it for configs that are solely
based on raw TCP, and it could still be imagined that some such might
exist with single connections (e.g. a log forwarder that buffers to
cover for the storage I/O latencies).

This should be backported to all HTX-enabled versions (2.0 and above).
2021-09-03 16:15:29 +02:00
Willy Tarreau
54496a6a5b MINOR: vars: make the vars() sample fetch function support a default value
It is quite common to see in configurations constructions like the
following one:

    http-request set-var(txn.bodylen) 0
    http-request set-var(txn.bodylen) req.hdr(content-length)
    ...
    http-request set-header orig-len %[var(txn.bodylen)]

The set-var() rules are almost always duplicated when manipulating
integers or any other value that is mandatory along operations. This is
a problem because it makes the configurations complicated to maintain
and slower than needed. And it becomes even more complicated when several
conditions may set the same variable because the risk of forgetting to
initialize it or to accidentally reset it is high.

This patch extends the var() sample fetch function to take an optional
argument which contains a default value to be returned if the variable
was not set. This way it becomes much simpler to use the variable, just
set it where needed, and read it with a fall back to the default value:

    http-request set-var(txn.bodylen) req.hdr(content-length)
    ...
    http-request set-header orig-len %[var(txn.bodylen,0)]

The default value is always passed as a string, thus it will experience
a cast to the output type. It doesn't seem userful to complicate the
configuration to pass an explicit type at this point.

The vars.vtc regtest was updated accordingly.
2021-09-03 12:08:54 +02:00
Willy Tarreau
e352b9dac7 MINOR: vars: make vars_get_by_* support an optional default value
In preparation for support default values when fetching variables, we
need to update the internal API to pass an extra argument to functions
vars_get_by_{name,desc} to provide an optional default value. This
patch does this and always passes NULL in this argument. var_to_smp()
was extended to fall back to this value when available.
2021-09-03 12:08:54 +02:00
Willy Tarreau
be7e00d134 CLEANUP: vars: factor out common code from vars_get_by_{desc,name}
The two functions vars_get_by_name() and vars_get_by_scope() perform
almost the same operations except that they differ from the way the
name and scope are retrieved. The second part in common is more
complex and involves locking, so better factor this one out into a
new function.

There is no other change than refactoring.
2021-09-03 11:43:35 +02:00
Willy Tarreau
e93bff4107 MEDIUM: vars: also support format strings in CLI's "set var" command
Most often "set var" on the CLI is used to set a string, and using only
expressions is not always convenient, particularly when trying to
concatenate variables sur as host names and paths.

Now the "set var" command supports an optional keyword before the value
to indicate its type. "expr" takes an expression just like before this
patch, and "fmt" a format string, making it work like the "set-var-fmt"
actions.

The VTC was updated to include a test on the format string.
2021-09-03 11:01:48 +02:00
Willy Tarreau
753d4db5f3 MINOR: vars: add a "set-var-fmt" directive to the global section
Just like the set-var-fmt action for tcp/http rules, the set-var-fmt
directive in global sections allows to pre-set process-wide variables
using a format string instead of a sample expression. This is often
more convenient when it is required to concatenate multiple fields,
or when emitting just one word.
2021-09-03 11:01:48 +02:00
Willy Tarreau
20b7a0f9ed MINOR: log: make log-format expressions completely usable outside of req/resp
The log-format strings are usable at plenty of places, but the expressions
using %[] were restricted to request or response context and nothing else.
This prevents from using them from the config context or the CLI, let's
relax this.
2021-09-03 11:01:48 +02:00
Willy Tarreau
9c20433aca CLEANUP: vars: name the temporary proxy "CFG" instead of "CLI" for global vars
We're using a dummy temporary proxy when creating global variables in
the configuration file, it was copied from the CLI's code and was
mistakenly called "CLI", better name it "CFG". It should not appear
anywhere except maybe when debugging cores.
2021-09-03 11:01:48 +02:00
Willy Tarreau
c767eebf1f BUG/MINOR: vars: do not talk about global section in CLI errors for set-var
When attempting to set a variable does not start with the "proc" scope on
the CLI, we used to emit "only proc is permitted in the global section"
which obviously is a leftover from the initial code.

This may be backported to 2.4.
2021-09-03 11:01:12 +02:00
Willy Tarreau
1402fef58a BUG/MINOR: vars: truncate the variable name in error reports about scope.
When a variable starts with the wrong scope, it is named without stripping
the extra characters that follow it, which usually are closing parenthesis.
Let's make sure we only report what is expected.

This may be backported to 2.4.
2021-09-03 11:01:12 +02:00
Willy Tarreau
c77bad2467 BUG/MEDIUM: vars: run over the correct list in release_store_rules()
In commit 9a621ae76 ("MEDIUM: vars: add a new "set-var-fmt" action")
we introduced the support for format strings in variables with the
ability to release them on exit, except that it's the wrong list that
was being scanned for the rule (http vs vars), resulting in random
crashes during deinit.

This was a recent commit in 2.5-dev, no backport is needed.
2021-09-03 11:01:12 +02:00
Willy Tarreau
9a621ae76d MEDIUM: vars: add a new "set-var-fmt" action
The set-var() action is convenient because it preserves the input type
but it's a pain to deal with when trying to concatenate values. The
most recurring example is when it's needed to build a variable composed
of the source address and the source port. Usually it ends up like this:

    tcp-request session set-var(sess.port) src_port
    tcp-request session set-var(sess.addr) src,concat(":",sess.port)

This is even worse when trying to aggregate multiple fields from stick-table
data for example. Due to this a lot of users instead abuse headers from HTTP
rules:

    http-request set-header(x-addr) %[src]:%[src_port]

But this requires some careful cleanups to make sure they won't leak, and
it's significantly more expensive to deal with. And generally speaking it's
not clean. Plus it must be performed for each and every request, which is
expensive for this common case of ip+port that doesn't change for the whole
session.

This patch addresses this limitation by implementing a new "set-var-fmt"
action which performs the same work as "set-var" but takes a format string
in argument instead of an expression. This way it becomes pretty simple to
just write:

    tcp-request session set-var-fmt(sess.addr) %[src]:%[src_port]

It is usable in all rulesets that already support the "set-var" action.
It is not yet implemented for the global "set-var" directive (which already
takes a string) and the CLI's "set var" command, which would definitely
benefit from it but currently uses its own parser and engine, thus it
must be reworked.

The doc and regtests were updated.
2021-09-02 21:22:22 +02:00
Willy Tarreau
54b96d9955 BUG/MINOR: vars: properly set the argument parsing context in the expression
When the expression called in "set-var" uses argments that require late
resolution, the context must be set. At the moment, any unknown argument
is misleadingly reported as "ACL":

    frontend f
        bind :8080
        mode http
        http-request set-var(proc.a) be_conn(foo)

   parsing [b1.cfg:4]: unable to find backend 'foo' referenced in arg 1 \
   of ACL keyword 'be_conn' in proxy 'f'.

Once the context is properly set, it now says the truth:

   parsing [b1.cfg:8]: unable to find backend 'foo' referenced in arg 1 \
   of sample fetch keyword 'be_conn' in http-request expression in proxy 'f'.

This may be backported but is not really important. If so, the preceeding
patches "BUG/MINOR: vars: improve accuracy of the rules used to check
expression validity" and "MINOR: sample: add missing ARGC_ entries" must
be backported as well.
2021-09-02 20:34:30 +02:00
Willy Tarreau
57467b8356 MINOR: sample: add missing ARGC_ entries
For a long time we couldn't have arguments in expressions used in
tcp-request, tcp-response etc rules. But now due to the variables
it's possible, and their context in case of failure to resolve an
argument (e.g. backend name not found) is not properly reported
because there is no arg context values in ARGC_* to report them.

Let's add a number of missing ones for tcp-request {connection,
session,content}, tcp-response content, tcp-check, the config
parser (for "set-var" in the global section) and the CLI parser
(for "set-var" on the CLI).
2021-09-02 19:43:20 +02:00
Willy Tarreau
843096d72a BUG/MINOR: vars: improve accuracy of the rules used to check expression validity
The set-var() expression naturally checks whether expressions are valid
in the context of the rule, but it fails to differentiate frontends from
backends. As such for tcp-content and http-request rules, it will only
accept frontend-compatible sample-fetches, excluding those declared with
SMP_UES_BKEND (a few such as be_id, be_name). For the response it accepts
the backend-compatible expressions only, though it seems that there are
no sample-fetch function that are valid only in the frontend's content,
so that should not cause any problem.

Note that while allowing valid configs to be used, the fix might also
uncover some incorrect configurations where some expressions currently
return nothing (e.g. something depending on frontend declared in a
backend), and which could be rejected, but there does not seem to be
any such keyword. Thus while it should be backported, better not backport
it too far (2.4 and possibly 2.3 only).
2021-09-02 19:23:43 +02:00
Willy Tarreau
2819210a83 BUG/MINOR: vars: fix set-var/unset-var exclusivity in the keyword parser
The parser checks first for "set-var" then "unset-var" from the updated
offset instead of testing it only when the other one fails, so it
validates this rule as "unset-var":

    http-request set-varunset-var(proc.a)

This should be backported everywhere relevant, though it's mostly harmless
as it's unlikely that some users are purposely writing this in their conf!
2021-09-02 18:46:22 +02:00
Willy Tarreau
bc1223be79 MINOR: http-rules: add a new "ignore-empty" option to redirects.
Sometimes it is convenient to remap large sets of URIs to new ones (e.g.
after a site migration for example). This can be achieved using
"http-request redirect" combined with maps, but one difficulty there is
that non-matching entries will return an empty response. In order to
avoid this, duplicating the operation as an ACL condition ending in
"-m found" is possible but it becomes complex and error-prone while it's
known that an empty URL is not valid in a location header.

This patch addresses this by improving the redirect rules to be able to
simply ignore the rule and skip to the next one if the result of the
evaluation of the "location" expression is empty. However in order not
to break existing setups, it requires a new "ignore-empty" keyword.

There used to be an ACT_FLAG_FINAL on redirect rules that's used during
the parsing to emit a warning if followed by another rule, so here we
only set it if the option is not there. The http_apply_redirect_rule()
function now returns a 3rd value to mention that it did nothing and
that this was not an error, so that callers can just ignore the rule.
The regular "redirect" rules were not modified however since this does
not apply there.

The map_redirect VTC was completed with such a test and updated to 2.5
and an example was added into the documentation.
2021-09-02 17:06:18 +02:00
Remi Tricot-Le Breton
942c167229 MINOR: connection: Add a connection error code sample fetch for backend side
The bc_conn_err and bc_conn_err_str sample fetches give the status of
the connection on the backend side. The error codes and error messages
are the same than the ones that can be raised by the fc_conn_err fetch.
2021-09-01 22:55:54 +02:00
Remi Tricot-Le Breton
163cdeba37 MINOR: ssl: Add new ssl_bc_hsk_err sample fetch
This new sample fetch along the ssl_bc_hsk_err_str fetch contain the
last SSL error of the error stack that occurred during the SSL
handshake (from the backend's perspective).
2021-09-01 22:55:39 +02:00
Willy Tarreau
87154e3010 BUG/MAJOR: queue: better protect a pendconn being picked from the proxy
The locking in the dequeuing process was significantly improved by commit
49667c14b ("MEDIUM: queue: take the proxy lock only during the px queue
accesses") in that it tries hard to limit the time during which the
proxy's queue lock is held to the strict minimum. Unfortunately it's not
enough anymore, because we take up the task and manipulate a few pendconn
elements after releasing the proxy's lock (while we're under the server's
lock) but the task will not necessarily hold the server lock since it may
not have successfully found one (e.g. timeout in the backend queue). As
such, stream_free() calling pendconn_free() may release the pendconn
immediately after the proxy's lock is released while the other thread
currently proceeding with the dequeuing tries to wake up the owner's
task and dies in task_wakeup().

One solution consists in releasing le proxy's lock later. But tests have
shown that we'd have to sacrifice a significant share of the performance
gained with the patch above (roughly a 20% loss).

This patch takes another approach. It adds a "del_lock" to each pendconn
struct, that allows to keep it referenced while the proxy's lock is being
released. It's mostly a serialization lock like a refcount, just to maintain
the pendconn alive till the task_wakeup() call is complete. This way we can
continue to release the proxy's lock early while keeping this one. It had
to be added to the few points where we're about to free a pendconn, namely
in pendconn_dequeue() and pendconn_unlink(). This way we continue to
release the proxy's lock very early and there is no performance degradation.

This lock may only be held under the queue's lock to prevent lock
inversion.

No backport is needed since the patch above was merged in 2.5-dev only.
2021-08-31 18:37:13 +02:00
Remi Tricot-Le Breton
fe21fe76bd MINOR: log: Add new "error-log-format" option
This option can be used to define a specific log format that will be
used in case of error, timeout, connection failure on a frontend... It
will be used for any log line concerned by the log-separate-errors
option. It will also replace the format of specific error messages
decribed in section 8.2.6.
If no "error-log-format" is defined, the legacy error messages are still
emitted and the other error logs keep using the regular log-format.
2021-08-31 12:13:08 +02:00
Remi Tricot-Le Breton
3d6350e108 MINOR: log: Remove log-error-via-logformat option
This option will be replaced by a "error-log-format" that enables to use
a dedicated log-format for connection error messages instead of the
regular log-format (in which most of the fields would be invalid in such
a case).
The "log-error-via-logformat" mechanism will then be replaced by a test
on the presence of such an error log format or not. If a format is
defined, it is used for connection error messages, otherwise the legacy
error log format is used.
2021-08-31 12:13:06 +02:00
Willy Tarreau
7b2108cad1 BUILD: tools: properly guard __GLIBC__ with defined()
The test on the glibc versions based on #if (__GLIBC > 2 ...) fails to
build under -Wundef, let's prepend defined(__GLIBC__) first.
2021-08-30 10:16:30 +02:00
Willy Tarreau
b131049eb5 BUILD: ssl: fix two remaining occurrences of #if USE_OPENSSL
One was in backend.c and the other one in hlua.c. No other candidate
was found with "git grep '^#if\s*USE'". It's worth noting that 3
other such tests exist for SSL_OP_NO_{SSLv3,TLSv1_1,TLSv1_2} but
that these ones are properly set to 0 in openssl-compat.h when not
defined.
2021-08-30 09:39:24 +02:00
Tim Duesterhus
18795d48a9 BUG/MINOR: tools: Fix loop condition in dump_text()
The condition should first check whether `bsize` is reached, before
dereferencing the offset. Even if this always works fine, due to the
string being null-terminated, this certainly looks odd.

Found using GitHub's CodeQL scan.

This bug traces back to at least 97c2ae13bc
(1.7.0+) and this patch should be backported accordingly.
2021-08-30 06:14:50 +02:00
Tim Duesterhus
1f269c12dc BUG/MINOR threads: Use get_(local|gm)time instead of (local|gm)time
Using localtime / gmtime is not thread-safe, whereas the `get_*` wrappers are.

Found using GitHub's CodeQL scan.

The use in sample_conv_ltime() can be traced back to at least
fac9ccfb70 (first appearing in 1.6-dev3), so all
supported branches with thread support are affected.
2021-08-30 06:14:32 +02:00
Willy Tarreau
fc89c3fd2b IMPORT: slz: silence a build warning with -Wundef
The test on FIND_OPTIMAL_MATCH for the experimental code can yield a
build warning when using -Wundef, let's turn it into a regular ifdef.

This is slz upstream commit 05630ae8f22b71022803809eb1e7deb707bb30fb
2021-08-28 12:47:57 +02:00
Willy Tarreau
e15615c1ff BUILD: activity: use #ifdef not #if on USE_MEMORY_PROFILING
This avoids most build warnings with -Wundef, and all other USE_* flags
are tested this way, let's do it there as well. See gh issue #1369.
2021-08-28 12:04:25 +02:00
Willy Tarreau
fe456c581f MINOR: time: add report_idle() to report process-wide idle time
Before threads were introduced in 1.8, idle_pct used to be a global
variable indicating the overall process idle time. Threads made it
thread-local, meaning that its reporting in the stats made little
sense, though this was not easy to spot. In 2.0, the idle_pct variable
moved to the struct thread_info via commit 81036f273 ("MINOR: time:
move the cpu, mono, and idle time to thread_info"). It made it more
obvious that the idle_pct was per thread, and also allowed to more
accurately measure it. But no more effort was made in that direction.

This patch introduces a new report_idle() function that accurately
averages the per-thread idle time over all running threads (i.e. it
should remain valid even if some threads are paused or stopped), and
makes use of it in the stats / "show info" reports.

Sending traffic over only two connections of an 8-thread process
would previously show this erratic CPU usage pattern:

  $ while :; do socat /tmp/sock1 - <<< "show info"|grep ^Idle;sleep 0.1;done
  Idle_pct: 30
  Idle_pct: 35
  Idle_pct: 100
  Idle_pct: 100
  Idle_pct: 100
  Idle_pct: 100
  Idle_pct: 100
  Idle_pct: 100
  Idle_pct: 35
  Idle_pct: 33
  Idle_pct: 100
  Idle_pct: 100
  Idle_pct: 100
  Idle_pct: 100
  Idle_pct: 100
  Idle_pct: 100

Now it shows this more accurate measurement:

  $ while :; do socat /tmp/sock1 - <<< "show info"|grep ^Idle;sleep 0.1;done
  Idle_pct: 83
  Idle_pct: 83
  Idle_pct: 83
  Idle_pct: 83
  Idle_pct: 83
  Idle_pct: 83
  Idle_pct: 83
  Idle_pct: 83
  Idle_pct: 83
  Idle_pct: 83
  Idle_pct: 83
  Idle_pct: 83
  Idle_pct: 83
  Idle_pct: 83
  Idle_pct: 83

This is not technically a bug but this lack of precision definitely affects
some users who rely on the idle_pct measurement. This should at least be
backported to 2.4, and might be to some older releases depending on users
demand.
2021-08-28 11:18:10 +02:00
Marcin Deranek
310a260e4a MEDIUM: config: Deprecate tune.ssl.capture-cipherlist-size
Deprecate tune.ssl.capture-cipherlist-size in favor of
tune.ssl.capture-buffer-size which better describes the purpose of the
setting.
2021-08-26 19:52:04 +02:00
Marcin Deranek
da0264a968 MINOR: sample: Add be2hex converter
Add be2hex converter to convert big-endian binary data into hex string
with optional string separators.
2021-08-26 19:48:34 +02:00
Marcin Deranek
40ca09c7bb MINOR: sample: Add be2dec converter
Add be2dec converter which allows to build JA3 compatible TLS
fingerprints by converting big-endian binary data into string
separated unsigned integers eg.

http-request set-header X-SSL-JA3 %[ssl_fc_protocol_hello_id],\
    %[ssl_fc_cipherlist_bin(1),be2dec(-,2)],\
    %[ssl_fc_extlist_bin(1),be2dec(-,2)],\
    %[ssl_fc_eclist_bin(1),be2dec(-,2)],\
    %[ssl_fc_ecformats_bin,be2dec(-,1)]
2021-08-26 19:48:34 +02:00
Marcin Deranek
959a48c116 MINOR: sample: Expose SSL captures using new fetchers
To be able to provide JA3 compatible TLS Fingerprints we need to expose
all Client Hello captured data using fetchers. Patch provides new
and modifies existing fetchers to add ability to filter out GREASE values:
- ssl_fc_cipherlist_*
- ssl_fc_ecformats_bin
- ssl_fc_eclist_bin
- ssl_fc_extlist_bin
- ssl_fc_protocol_hello_id
2021-08-26 19:48:34 +02:00
Marcin Deranek
769fd2e447 MEDIUM: ssl: Capture more info from Client Hello
When we set tune.ssl.capture-cipherlist-size to a non-zero value
we are able to capture cipherlist supported by the client. To be able to
provide JA3 compatible TLS fingerprinting we need to capture more
information from Client Hello message:
- SSL Version
- SSL Extensions
- Elliptic Curves
- Elliptic Curve Point Formats
This patch allows HAProxy to capture such information and store it for
later use.
2021-08-26 19:48:33 +02:00
Willy Tarreau
5ef965606b BUG/MINOR: lua: use strlcpy2() not strncpy() to copy sample keywords
The lua initialization code which creates the Lua mapping of all converters
and sample fetch keywords makes use of strncpy(), and as such can take ages
to start with large values of tune.bufsize because it spends its time zeroing
gigabytes of memory for nothing. A test performed with an extreme value of
16 MB takes roughly 4 seconds, so it's possible that some users with huge
1 MB buffers (e.g. for payload analysis) notice a small startup latency.
However this does not affect config checks since the Lua stack is not yet
started. Let's replace this with strlcpy2().

This should be backported to all supported versions.
2021-08-26 16:57:48 +02:00
Amaury Denoyelle
dd56520cdf BUG/MINOR: resolvers: mark servers with name-resolution as non purgeable
When a server is configured with name-resolution, resolvers objects are
created with reference to this server. Thus the server is marked as non
purgeable to prevent its removal at runtime.

This does not need to be backport.
2021-08-26 15:53:17 +02:00
William Lallemand
a39e6266d1 BUG/MINOR: proxy: don't dump servers of internal proxies
Patch 211c967 ("MINOR: httpclient: add the server to the proxy") broke
the reg-tests that do a "show servers state".

Indeed the servers of the proxies flagged with PR_CAP_INT are dumped in
the output of this CLI command.

This patch fixes the issue par ignoring the PR_CA_INT proxies in the
dump.
2021-08-25 18:15:31 +02:00
Dragan Dosen
61aa4428c1 BUG/MINOR: base64: base64urldec() ignores padding in output size check
Without this fix, the decode function would proceed even when the output
buffer is not large enough, because the padding was not considered. For
example, it would not fail with the input length of 23 and the output
buffer size of 15, even the actual decoded output size is 17.

This patch should be backported to all stable branches that have a
base64urldec() function available.
2021-08-25 16:14:14 +02:00
Amaury Denoyelle
14c3c5c121 MEDIUM: server: allow to remove servers at runtime except non purgeable
Relax the condition on "delete server" CLI handler to be able to remove
all servers, even non dynamic, except if they are flagged as non
purgeable.

This change is necessary to extend the use cases for dynamic servers
with reload. It's expected that each dynamic server created via the CLI
is manually commited in the haproxy configuration by the user. Dynamic
servers will be present on reload only if they are present in the
configuration file. This means that non-dynamic servers must be allowed
to be removable at runtime.

The dynamic servers removal reg-test has been updated and renamed to
reflect its purpose. A new test is present to check that non-purgeable
servers cannot be removed.
2021-08-25 15:53:54 +02:00
Amaury Denoyelle
86f3707d14 MINOR: server: mark servers referenced by LUA script as non purgeable
Each server that is retrieved by a LUA script is marked as non
purgeable. Note that for this to work, the script must have been
executed already once.
2021-08-25 15:53:54 +02:00
Amaury Denoyelle
0626961ad3 MINOR: server: mark referenced servers as non purgeable
Mark servers that are referenced by configuration elements as non
purgeable. This includes the following list :
- tracked servers
- servers referenced in a use-server rule
- servers referenced in a sample fetch
2021-08-25 15:53:54 +02:00
Amaury Denoyelle
bc2ebfa5a4 MEDIUM: server: extend refcount for all servers
In a future patch, it will be possible to remove at runtime every
servers, both static and dynamic. This requires to extend the server
refcount for all instances.

First, refcount manipulation functions have been renamed to better
express the API usage.

* srv_refcount_use -> srv_take
The refcount is always initialize to 1 on the server creation in
new_server. It's also incremented for each check/agent configured on a
server instance.

* free_server -> srv_drop
This decrements the refcount and if null, the server is freed, so code
calling it must not use the server reference after it. As a bonus, this
function now returns the next server instance. This is useful when
calling on the server loop without having to save the next pointer
before each invocation.

In these functions, remove the checks that prevent refcount on
non-dynamic servers. Each reference to "dynamic" in variable/function
naming have been eliminated as well.
2021-08-25 15:53:54 +02:00
Amaury Denoyelle
0a8d05d31c BUG/MINOR: stats: use refcount to protect dynamic server on dump
A dynamic server may be deleted at runtime at the same moment when the
stats applet is pointing to it. Use the server refcount to prevent
deletion in this case.

This should be backported up to 2.4, with an observability period of 2
weeks. Note that it requires the dynamic server refcounting feature
which has been implemented on 2.5; the following commits are required :

- MINOR: server: implement a refcount for dynamic servers
- BUG/MINOR: server: do not use refcount in free_server in stopping mode
- MINOR: server: return the next srv instance on free_server
2021-08-25 15:53:43 +02:00
Amaury Denoyelle
f5c1e12e44 MINOR: server: return the next srv instance on free_server
As a convenience, return the next server instance from servers list on
free_server.

This is particularily useful when using this function on the servers
list without having to save of the next pointer before calling it.
2021-08-25 15:29:19 +02:00
devnexen@gmail.com
21185970c1 MINOR: proc: setting the process to produce a core dump on FreeBSD.
using the procctl api to set the current process as traceable, thus being able to produce a core dump as well.

making it as compile option if not wished or using freebsd prior to 11.x (last no EOL release).
2021-08-25 05:14:27 +02:00
Ilya Shipitsin
ff0f278860 CLEANUP: assorted typo fixes in the code and comments
This is 26th iteration of typo fixes
2021-08-25 05:13:31 +02:00
William Lallemand
957ab13d7b BUILD: httpclient: fix build without OpenSSL
Add some defines around the ssl server so we can build without OpenSSL.
2021-08-24 18:33:28 +02:00
William Lallemand
4463b17fe3 BUG/MINOR: httpclient: fix Host header
THe http_update_update_host function takes an URL and extract the domain
to use as a host header. However it only update an existing host header
and does not create one.

This patch add an empty host header so the function can update it.
2021-08-24 17:53:03 +02:00
William Lallemand
211c9679c8 MINOR: httpclient: add the server to the proxy
Add the raw and ssl server to the proxy list so they can be freed during
the deinit() of HAProxy. As a side effect the 2 servers need to have a
different ID so the SSL one was renamed "<HTTPSCLIENT>".
2021-08-24 17:18:13 +02:00
William Lallemand
cfcbe9ebd9 MINOR: httpclient: set verify none on the https server
There is currently no way to specify the CA to verify from the
httpclient API. Sets the verify to none so we can still do https
request.
2021-08-24 17:15:58 +02:00
Dragan Dosen
f3899ddbcb BUG/MEDIUM: base64: check output boundaries within base64{dec,urldec}
Ensure that no more than olen bytes is written to the output buffer,
otherwise we might experience an unexpected behavior.

While the original code used to validate that the output size was
always large enough before starting to write, this validation was
later broken by the commit below, allowing to 3-byte blocks to
areas whose size is not multiple of 3:

  commit ed697e4856
  Author: Emeric Brun <ebrun@haproxy.com>
  Date:   Mon Jan 14 14:38:39 2019 +0100

    BUG/MINOR: base64: dec func ignores padding for output size checking

    Decode function returns an error even if the ouptut buffer is
    large enought because the padding was not considered. This
    case was never met with current code base.

For base64urldec(), it's basically the same problem except that since
the input format supports arbitrary lengths, the problem has always
been there since its introduction in 2.4.

This should be backported to all stable branches having a backport of
the patch above (i.e. 2.0), with some adjustments depending on the
availability of the base64dec() and base64urldec().
2021-08-24 16:10:49 +02:00
William Lallemand
76ad371b86 BUG/MINOR: httpclient: remove deinit of the httpclient
The httpclient does a free of the servers and proxies it uses, however
since we are including them in the global proxy list, haproxy already
free them during the deinit. We can safely remove these free.
2021-08-24 15:11:03 +02:00
Willy Tarreau
ece4c4a352 BUG/MINOR: stick-table: fix the sc-set-gpt* parser when using expressions
The sc-set-gpt0() parser was extended in 2.1 by commit 0d7712dff ("MINOR:
stick-table: allow sc-set-gpt0 to set value from an expression") to support
sample expressions in addition to plain integers. However there is a
subtlety there, which is that while the arg position must be incremented
when parsing an integer, it must not be touched when calling an expression
since the expression parser already does it.

The effect is that rules making use of sc-set-gpt0() followed by an
expression always ignore one word after that expression, and will typically
fail to parse if followed by an "if" as the parser will restart after the
"if". With no condition it's different because an empty condition doesn't
result in trying to parse anything.

This patch moves the increment at the right place and adds a few
explanations for a code part that was far from being obvious.

This should be backported to branches having the commit above (2.1+).
2021-08-24 15:05:48 +02:00
William Lallemand
8b673f0fe3 CLEANUP: ssl: remove useless check on p in openssl_version_parser()
Remove a  useless check on a pointer which reports a NULL dereference on
coverity.

Fixes issue #1358.
2021-08-22 13:36:11 +02:00
William Lallemand
3aeb3f9347 MINOR: cfgcond: implements openssl_version_atleast and openssl_version_before
Implements a way of checking the running openssl version:

If the OpenSSL support was not compiled within HAProxy it will returns a
error, so it's recommanded to do a SSL feature check before:

	$ ./haproxy -cc 'feature(OPENSSL) && openssl_version_atleast(0.9.8zh) && openssl_version_before(3.0.0)'

This will allow to select the SSL reg-tests more carefully.
2021-08-22 00:30:24 +02:00
William Lallemand
44d862d8d4 MINOR: ssl: add an openssl version string parser
openssl_version_parser() parse a string in the OpenSSL version format
which is documented here:

https://www.openssl.org/docs/man1.1.1/man3/OPENSSL_VERSION_NUMBER.html

The function returns an unsigned int that could be used for comparing
openssl versions.
2021-08-21 23:44:02 +02:00
devnexen@gmail.com
c4e5232db8 MINOR: tools: add FreeBSD support to get_exec_path()
FreeBSD stores the absolute path into the auxiliary vector as well.
The auxiliary vector is found in __elf_aux_vector there.
2021-08-20 17:33:32 +02:00
Willy Tarreau
1e7bef17df MINOR: hlua: take the global Lua lock inside a global function
Some users are facing huge CPU usage or even watchdog panics due to
the Lua global lock when many threads compete on it, but they have
no way to see that in the usual dumps. We take the lock at 2 or 3
places only, thus it's trivial to move it to a global function so
that stack dumps will now explicitly show it, increasing the change
that it rings a bell and someone suggests switch to lua-load-per-thread:

  Current executing Lua from a stream analyser -- stack traceback:
      loop.lua:1: in function line 1
  call trace(27):
  |       0x5ff157 [48 83 c4 10 5b 5d 41 5c]: wdt_handler+0xf7/0x104
  | 0x7fe37fe82690 [48 c7 c0 0f 00 00 00 0f]: libpthread:+0x13690
  |       0x614340 [66 48 0f 7e c9 48 01 c2]: main+0x1e8a40
  |       0x607b85 [48 83 c4 08 48 89 df 31]: main+0x1dc285
  |       0x6070bc [48 8b 44 24 20 48 8b 14]: main+0x1db7bc
  |       0x607d37 [41 89 c4 89 44 24 1c 83]: lua_resume+0xc7/0x214
  |       0x464ad6 [83 f8 06 0f 87 f1 01 00]: main+0x391d6
  |       0x4691a7 [83 f8 06 0f 87 03 20 fc]: main+0x3d8a7
  |       0x51dacb [85 c0 74 61 48 8b 5d 20]: sample_process+0x4b/0xf7
  |       0x51e55c [48 85 c0 74 3f 64 48 63]: sample_fetch_as_type+0x3c/0x9b
  |       0x525613 [48 89 c6 48 85 c0 0f 84]: sess_build_logline+0x2443/0x3cae
  |       0x4af0be [4c 63 e8 4c 03 6d 10 4c]: http_apply_redirect_rule+0xbfe/0xdf8
  |       0x4af523 [83 f8 01 19 c0 83 e0 03]: main+0x83c23
  |       0x4b2326 [83 f8 07 0f 87 99 00 00]: http_process_req_common+0xf6/0x15f6
  |       0x4d5b30 [85 c0 0f 85 9f f5 ff ff]: process_stream+0x2010/0x4e18

It also allows "perf top" to directly show the time spent on this lock.

This may be backported to some stable versions as it improves the
overall debuggability.
2021-08-20 17:33:26 +02:00
William Lallemand
2a8fe8bb48 MINOR: httpclient: cleanup the include files
Include the correct .h files in http_client.c and http_client.h.

The api.h is needed in http_client.c and http_client-t.h is now include
directly from http_client.h
2021-08-20 14:25:15 +02:00
William Lallemand
0d6f7790fb BUG/MINOR: httpclient: check if hdr_num is not 0
Check if hdr_num is not 0 before allocating or copying the headers to
the hc->hdrs space.
2021-08-20 11:59:49 +02:00
William Lallemand
dfc3f8906d BUG/MINOR: httpclient/cli: change the appctx test in the callbacks
The callbacks of the CLI httpclient are testing the appctx pointer
before doing the appctx_wakeup but was dereferencing the appctx pointer
before.
2021-08-20 11:53:16 +02:00
William Lallemand
b70203017b BUG/MINOR: httpclient: fix uninitialized sl variable
Reported by coverity in ticket #1355

  CID 1461505:  Memory - illegal accesses  (UNINIT)
  Using uninitialized value "sl".

Fix the problem by initializing sl to NULL.
2021-08-20 11:53:16 +02:00
Willy Tarreau
0e72e40f7e BUG/MINOR: http_client: make sure to preset the proxy's default settings
Proxies must call proxy_preset_defaults() to initialize their settings
that are usually learned from defaults sections (e.g. connection retries,
pool purge delay etc). At the moment there was likely no impact, but not
doing so could cause trouble soon when using the client more extensively
or when new defaults are introduced and failed to be initialized.

No backport is needed.
2021-08-20 10:23:12 +02:00
Willy Tarreau
d3dbfd9085 BUG/MEDIUM: cfgparse: do not allocate IDs to automatic internal proxies
Recent commit 83614a9fb ("MINOR: httpclient: initialize the proxy") broke
reg tests that match the output of "show stats" or "show servers state"
because it changed the proxies' numeric ID.

In fact it did nothing wrong, it just registers a proxy and adds it at
the head of the list. But the automatic numbering scheme, which was made
to make sure that temporarily disabled proxies in the config keep their
ID instead of shifting all others, sees one more proxy and increments
next_pxid for all subsequent proxies.

This patch avoids this by not assigning automatic IDs to such internal
proxies, leaving them with their ID of -1, and by not shifting next_pxid
for them. This is important because the user might experience them
appearing or disappearing depending on apparently unrelated config
options or build options, and this must not cause visible proxy IDs
to change (e.g. stats or minitoring may break).

Though the issue has always been there, it only became a problem with
the recent proxy additions so there is no need to backport this.
2021-08-20 10:22:41 +02:00
William Lallemand
b0281a4903 MINOR: proxy: check if p is NULL in free_proxy()
Check if p is NULL before trying to do anything  in free_proxy(),
like most free()-like function do.
2021-08-20 10:20:56 +02:00
William Lallemand
4c395fce21 MINOR: server: check if srv is NULL in free_server()
Check if srv is NULL before trying to do anything  in free_server(),
like most free()-like function do.
2021-08-20 10:20:51 +02:00
Remi Tricot-Le Breton
f95c29546c BUILD/MINOR: ssl: Fix compilation with OpenSSL 1.0.2
The X509_STORE_CTX_get0_cert did not exist yet on OpenSSL 1.0.2 and
neither did X509_STORE_CTX_get0_chain, which was not actually needed
since its get1 equivalent already existed.
2021-08-20 10:05:58 +02:00
Willy Tarreau
46b7dff8f0 BUG/MEDIUM: h2: match absolute-path not path-absolute for :path
RFC7540 states that :path follows RFC3986's path-absolute. However
that was a bug introduced in the spec between draft 04 and draft 05
of the spec, which implicitly causes paths starting with "//" to be
forbidden. HTTP/1 (and now HTTP core semantics) made it explicit
that the request-target in origin-form follows a purposely defined
absolute-path defined as 1*(/ segment) to explicitly allow "//".

http2bis now fixes this by relying on absolute-path so that "//"
becomes valid and matches other versions. Full discussion here:

  https://lists.w3.org/Archives/Public/ietf-http-wg/2021JulSep/0245.html

This issue appeared in haproxy with commit 4b8852c70 ("BUG/MAJOR: h2:
verify that :path starts with a '/' before concatenating it") when
making the checks on :path fully comply with the spec, and was backported
as far as 2.0, so this fix must be backported there as well to allow
"//" in H2 again.
2021-08-19 23:38:18 +02:00
Remi Tricot-Le Breton
74f6ab6e87 MEDIUM: ssl: Keep a reference to the client's certificate for use in logs
Most of the SSL sample fetches related to the client certificate were
based on the SSL_get_peer_certificate function which returns NULL when
the verification process failed. This made it impossible to use those
fetches in a log format since they would always be empty.

The patch adds a reference to the X509 object representing the client
certificate in the SSL structure and makes use of this reference in the
fetches.

The reference can only be obtained in ssl_sock_bind_verifycbk which
means that in case of an SSL error occurring before the verification
process ("no shared cipher" for instance, which happens while processing
the Client Hello), we won't ever start the verification process and it
will be impossible to get information about the client certificate.

This patch also allows most of the ssl_c_XXX fetches to return a usable
value in case of connection failure (because of a verification error for
instance) by making the "conn->flags & CO_FL_WAIT_XPRT" test (which
requires a connection to be established) less strict.

Thanks to this patch, a log-format such as the following should return
usable information in case of an error occurring during the verification
process :
    log-format "DN=%{+Q}[ssl_c_s_dn] serial=%[ssl_c_serial,hex] \
                hash=%[ssl_c_sha1,hex]"

It should answer to GitHub issue #693.
2021-08-19 23:26:05 +02:00
William Lallemand
2484da5ebc MINOR: httpclient/cli: change the User-Agent to "HAProxy"
Change the User-Agent from "HAProxy HTTP client" to "HAProxy" as the
previous name is not valid according to RFC 7231#5.5.3.

This patch fixes issue #1354.
2021-08-19 15:55:19 +02:00
William Lallemand
03a4eb154f MINOR: httpclient/cli: implement a simple client over the CLI
This commit implements an HTTP Client over the CLI, this was made as
working example for the HTTP Client API.

It usable over the CLI by specifying a method and an URL:

    echo "httpclient GET http://127.0.0.1:8000/demo.file" | socat /tmp/haproxy.sock -

Only IP addresses are accessibles since the API does not allow to
resolve addresses yet.
2021-08-18 18:25:05 +02:00
William Lallemand
33b0d095cc MINOR: httpclient: implement a simple HTTP Client API
This commit implements a very simple HTTP Client API.

A client can be operated by several functions:

    - httpclient_new(), httpclient_destroy(): create
      and destroy the struct httpclient instance.

    - httpclient_req_gen(): generate a complete HTX request using the
      the absolute URL, the method and a list of headers. This request
      is complete and sets the HTX End of Message flag. This is limited
      to small request we don't need a body.

    - httpclient_start() fill a sockaddr storage with a IP extracted
      from the URL (it cannot resolve an fqdm for now), start the
      applet. It also stores the ptr of the caller which could be an
      appctx or something else.

   - hc->ops contains a list of callbacks used by the
     HTTPClient, they should be filled manually after an
     httpclient_new():

        * res_stline(): the client received a start line, its content
          will be stored in hc->res.vsn, hc->res.status, hc->res.reason

        * res_headers(): the client received headers, they are stored in
          hc->res.hdrs.

        * res_payload(): the client received some payload data, they are
        stored in the hc->res.buf buffer and could be extracted with the
        httpclient_res_xfer() function, which takes a destination buffer
        as a parameter

        * res_end(): this callback is called once we finished to receive
        the response.
2021-08-18 17:36:32 +02:00
William Lallemand
83614a9fbe MINOR: httpclient: initialize the proxy
Initialize a proxy which contain a server for the raw HTTP, and another
one for the HTTPS. This proxy will use the global server log definition
and the 'option httplog' directive.

This proxy is internal and will only be used for the HTTP Client API.
2021-08-18 17:35:48 +02:00
Willy Tarreau
b5d2b9e154 BUG/MEDIUM: h2: give :authority precedence over Host
The wording regarding Host vs :authority in RFC7540 is ambiguous as it
says that an intermediary must produce a host header from :authority if
Host is missing, but, contrary to HTTP/1.1, doesn't say anything regarding
the possibility that Host and :authority differ, which leaves Host with
higher precedence there. In addition it mentions that clients should use
:authority *instead* of Host, and that H1->H2 should use :authority only
if the original request was in authority form. This leaves some gray
area in the middle of the chain for fully valid H2 requests arboring a
Host header that are forwarded to the other side where it's possible to
drop the Host header and use the authority only after forwarding to a
second H2 layer, thus possibly seeing two different values of Host at
a different stage. There's no such issue when forwarding from H2 to H1
as the authority is dropped only only the Host is kept.

Note that the following request is sufficient to re-normalize such a
request:

   http-request set-header host %[req.hdr(host)]

The new spec in progress (draft-ietf-httpbis-http2bis-03) addresses
this trouble by being a bit is stricter on these rules. It clarifies
that :authority must always be used instead of Host and that Host ought
to be ignored. This is much saner as it avoids to convey two distinct
values along the chain. This becomes the protocol-level equivalent of:

   http-request set-uri %[url]

So this patch does exactly this, which we were initially a bit reluctant
to do initially by lack of visibility about other implementations'
expectations. In addition it slightly simplifies the Host header field
creation by always placing it first in the list of headers instead of
last; this could also speed up the look up a little bit.

This needs to be backported to 2.0. Non-HTX versions are safe regarding
this because they drop the URI during the conversion to HTTP/1.1 so
only Host is used and transmitted.

Thanks to Tim Dsterhus for reporting that one.
2021-08-17 10:21:07 +02:00
Willy Tarreau
89265224d3 BUG/MAJOR: h2: enforce stricter syntax checks on the :method pseudo-header
Before HTX was introduced, all the HTTP request elements passed in
pseudo-headers fields were used to build an HTTP/1 request whose syntax
was then scrutinized by the HTTP/1 parser, leaving no room to inject
invalid characters.

While NUL, CR and LF are properly blocked, it is possible to inject
spaces in the method so that once translated to HTTP/1, fields are
shifted by one spcae, and a lenient HTTP/1 server could possibly be
fooled into using a part of the method as the URI. For example, the
following request:

   H2 request
     :method: "GET /admin? HTTP/1.1"
     :path:   "/static/images"

would become:

   GET /admin? HTTP/1.1 /static/images HTTP/1.1

It's important to note that the resulting request is *not* valid, and
that in order for this to be a problem, it requires that this request
is delivered to an already vulnerable HTTP/1 server.

A workaround here is to reject malformed methods by placing this rule
in the frontend or backend, at least before leaving haproxy in H1:

   http-request reject if { method -m reg [^A-Z0-9] }

Alternately H2 may be globally disabled by commenting out the "alpn"
directive on "bind" lines, and by rejecting H2 streams creation by
adding the following statement to the global section:

   tune.h2.max-concurrent-streams 0

This patch adds a check for each character of the method to make sure
they belong to the ones permitted in a token, as mentioned in RFC7231#4.1.

This should be backported to versions 2.0 and above. For older versions
not having HTX_FL_PARSING_ERROR, a "goto fail" works as well as it
results in a protocol error at the stream level. Non-HTX versions are
safe because the resulting invalid request will be rejected by the
internal HTTP/1 parser.

Thanks to Tim Dsterhus for reporting that one.
2021-08-17 10:18:52 +02:00
Willy Tarreau
4b8852c70d BUG/MAJOR: h2: verify that :path starts with a '/' before concatenating it
Tim Dsterhus found that while the H2 path is checked for non-emptiness,
invalid chars and '*', a test is missing to verify that except for '*',
it always starts with exactly one '/'. During the reconstruction of the
full URI when passing to HTX, this missing test allows to affect the
apparent authority by appending a port number or a suffix name.

This only affects H2-to-H2 communications, as H2-to-H1 do not use the
full URI. Like for previous fix, the following rule inserted before
other ones in the frontend is sufficient to renormalize the internal
URI and let haproxy see the same authority as the target server:

    http-request set-uri %[url]

This needs to be backported to 2.2. Earlier versions do not rebuild a
full URI using the authority and will fail on the malformed path at the
HTTP layer, so they are safe.
2021-08-17 10:16:22 +02:00
Willy Tarreau
a495e0d948 BUG/MAJOR: h2: verify early that non-http/https schemes match the valid syntax
While we do explicitly check for strict character sets in the scheme,
this is only done when extracting URL components from an assembled one,
and we have special handling for "http" and "https" schemes directly in
the H2-to-HTX conversion. Sadly, this lets all other ones pass through
if they start exactly with "http://" or "https://", allowing the
reconstructed URI to start with a different looking authority if it was
part of the scheme.

It's interesting to note that in this case the valid authority is in
the Host header and that the request will only be wrong if emitted over
H2 on the backend side, since H1 will not emit an absolute URI by
default and will drop the scheme. So in essence, this is a variant of
the scheme-based attack described below in that it only affects H2-H2
and not H2-H1 forwarding:

   https://portswigger.net/research/http2

As such, a simple workaround consists in just inserting the following
rule before other ones in the frontend, which will have for effect to
renormalize the authority in the request line according to the
concatenated version (making haproxy see the same authority and host
as what the target server will see):

   http-request set-uri %[url]

This patch simply adds the missing syntax checks for non-http/https
schemes before the concatenation in the H2 code. An improvement may
consist in the future in splitting these ones apart in the start
line so that only the "url" sample fetch function requires to access
them together and that all other places continue to access them
separately. This will then allow the core code to perform such checks
itself.

The patch needs to be backported as far as 2.2. Before 2.2 the full
URI was not being reconstructed so the scheme and authority part were
always dropped from H2 requests to leave only origin requests. Note
for backporters: this depends on this previous patch:

  MINOR: http: add a new function http_validate_scheme() to validate a scheme

Many thanks to Tim Dsterhus for figuring that one and providing a
reproducer.
2021-08-17 10:16:22 +02:00
Willy Tarreau
d3d8d03d98 MINOR: http: add a new function http_validate_scheme() to validate a scheme
While http_parse_scheme() extracts a scheme from a URI by extracting
exactly the valid characters and stopping on delimiters, this new
function performs the same on a fixed-size string.
2021-08-17 10:16:22 +02:00
David Carlier
bd2ccedcc5 BUILD: tools: get the absolute path of the current binary on NetBSD.
NetBSD stores the absolute path into the auxiliary vector as well.
2021-08-17 09:54:28 +02:00
Ilya Shipitsin
01881087fc CLEANUP: assorted typo fixes in the code and comments
This is 25th iteration of typo fixes
2021-08-16 12:37:59 +02:00
Christopher Faulet
e48d1dc2d9 BUG/MINOR: lua/filters: Return right code when txn:done() is called
txn functions can now be called from an action or a filter context. Thus the
return code must be adapted depending on this context. From an action, act.ABORT
is returned. From a filter, -1 is returned. It is the filter error code.

This bug only affects 2.5-dev. No backport needed.
2021-08-13 17:14:47 +02:00
Christopher Faulet
26eb5ea352 BUG/MINOR: filters: Always set FLT_END analyser when CF_FLT_ANALYZE flag is set
CF_FLT_ANALYZE flags may be set before the FLT_END analyser. Thus if an error is
triggered in the mean time, this may block the stream and prevent it to be
released. It is indeed a problem only for the response channel because the
response analysers may be skipped on early errors.

So, to prevent any issue, depending on the code path, the FLT_END analyser is
systematically set when the CF_FLT_ANALYZE flag is set.

This patch must be backported in all stable branches.
2021-08-13 17:14:47 +02:00
William Lallemand
2c04a5a03d MINOR: proxy: disable warnings for internal proxies
The internal proxies should be part of the proxies list, because of
this, the check_config_validity() fonction could emit warnings about
these proxies.

This patch disables 3 startup warnings for internal proxies:

- "has no 'bind' directive" (this one was already ignored for the CLI
frontend, but we made it generic instead)
- "missing timeouts"
- "log format ignored"
2021-08-13 15:34:16 +02:00
William Lallemand
6640dbb524 MINOR: cli: delare the CLI frontend as an internal proxy
Declare the CLI frontend as an internal proxy so we can check the
PR_CAP_INT flag instead of the global.fe_cli pointer for generic use
cases.
2021-08-13 15:34:10 +02:00
Emeric Brun
bc5c821cc2 BUG/MEDIUM: cfgcheck: verify existing log-forward listeners during config check
User reported that the config check returns an error with the message:
"Configuration file has no error but will not start (no listener) => exit(2)."
if the configuration present only a log-forward section with bind or dgram-bind
listeners but no listen/backend nor peer sections.

The process checked if there was 'peers' section avalaible with
an internal frontend (and so a listener) or a 'listen/backend'
section not disabled with at least one configured listener (into the
global proxies_list). Since the log-forward proxies appear in a
different list, they were not checked.

This patch adds a lookup on the 'log-forward' proxies list to check
if one of them presents a listener and is not disabled. And
this is done only if there was no available listener found into
'listen/backend' sections.

I have also studied how to re-work this check considering the 'listeners'
counter used after startup/init to keep the same algo and avoid further
mistakes but currently this counter seems increased during config parsing
and if a proxy is disabled, decreased during startup/init which is done
after the current config check. So the fix still not rely on this
counter.

This patch should fix the github issue #1346

This patch should be backported as far as 2.3 (so on branches
including the "log-forward" feature)
2021-08-13 11:21:57 +02:00
Christopher Faulet
c86bb87f10 BUG/MINOR: lua: Properly catch alloc errors when parsing lua filter directives
When a lua filter declaration is parsed, some allocation errors were not
properly handled. In addition, we must be sure the filter identifier is defined
in lua to duplicate it when the filter configuration is filled.

This patch fix a defect reported in the issue #1347. It only concerns
2.5-dev. No backport needed.
2021-08-13 08:42:00 +02:00
Christopher Faulet
70c4345dbc BUG/MINOR: lua: Properly check negative offset in Channel/HttpMessage functions
In Channel and HTTPMessage classes, several functions uses an offset that
may be negative to start from the end of incoming data. But, after
calculation, the offset must never be negative. However, there is a bug
because of a bad cast to unsigned when "input + offset" is performed. The
result must be a signed integer.

This patch should fix most of defects reported in the issue #1347. It only
affects 2.5-dev. No backport needed.
2021-08-13 08:36:42 +02:00
Christopher Faulet
eae8afaa60 MINOR: filters/lua: Support the HTTP filtering from filters written in lua
Now an HTTPMessage class is available to manipulate HTTP message from a filter
it is possible to bind HTTP filters callback function on lua functions. Thus,
following methods may now be defined by a lua filter:

  * Filter:http_headers(txn, http_msg)
  * Filter:http_payload(txn, http_msg, offset, len)
  * Filter:http_end(txn, http_msg)

http_headers() and http_end() may return one of the constant filter.CONTINUE,
filter.WAIT or filter.ERROR. If nothing is returned, filter.CONTINUE is used as
the default value. On its side, http_payload() may return the amount of data to
forward. If nothing is returned, all incoming data are forwarded.

For now, these functions are not allowed to yield because this interferes with
the filter workflow.
2021-08-12 08:57:07 +02:00
Christopher Faulet
78c35471f8 MINOR: filters/lua: Add request and response HTTP messages in the lua TXN
When a lua TXN is created from a filter context, the request and the response
HTTP message objects are accessible from ".http_req" and ".http_res" fields. For
an HTTP proxy, these objects are always defined. Otherwise, for a TCP proxy, no
object is created and nil is used instead. From any other context (action or
sample fetch), these fields don't exist.
2021-08-12 08:57:07 +02:00
Christopher Faulet
df97ac4584 MEDIUM: filters/lua: Add HTTPMessage class to help HTTP filtering
This new class exposes methods to manipulate HTTP messages from a filter
written in lua. Like for the HTTP class, there is a bunch of methods to
manipulate the message headers. But there are also methods to manipulate the
message payload. This part is similar to what is available in the Channel
class. Thus the payload can be duplicated, erased, modified or
forwarded. For now, only DATA blocks can be retrieved and modified because
the current API is limited. No HTTPMessage method is able to yield. Those
manipulating the headers are always called on messages containing all the
headers, so there is no reason to yield. Those manipulating the payload are
called from the http_payload filters callback function where yielding is
forbidden.

When an HTTPMessage object is instantiated, the underlying Channel object
can be retrieved via the ".channel" field.

For now this class is not used because the HTTP filtering is not supported
yet. It will be the purpose of another commit.

There is no documentation for now.
2021-08-12 08:57:07 +02:00
Christopher Faulet
c404f1126c MEDIUM: filters/lua: Support declaration of some filter callback functions in lua
It is now possible to write some filter callback functions in lua. All
filter callbacks are not supported yet but the mechanism to call them is now
in place. Following method may be defined in the Lua filter class to be
bound on filter callbacks:

  * Filter:start_analyse(txn, chn)
  * Filter:end_analyse(txn, chn)
  * Filter:tcp_payload(txn, chn, offset, length)

hlua_filter_callback() function is responsible to call the good lua function
depending on the filter callback function. Using some flags it is possible
to allow a lua call to yield or not, to retrieve a return value or not, and
to specify if a channel or an http message must be passed as second
argument. For now, the HTTP part has not been added yet. It is also possible
to add extra argument adding them on the stack before the call.

3 new functions are exposed by the global object "filter". The first one,
filter.wake_time(ms_delay), to set the wake_time when a Lua callback
function yields (if allowed). The two others,
filter.register_data_filter(filter, chn) and
filter.unregister_data_filter(filter, chn), to enable or disable the data
filtering on a channel for a specific lua filter instance.

start_analyse() and end_analyse() may return one of the constant
filter.CONTINUE, filter.WAIT or filter.ERROR. If nothing is returned,
filter.CONTINUE is used as the default value. On its side, tcp_payload() may
return the amount of data to forward. If nothing is returned, all incoming
data are forwarded.

For now, these functions are not allowed to yield because this interferes
with the filter workflow.

Here is a simple example :

    MyFilter = {}
    MyFilter.id = "My Lua filter"
    MyFilter.flags = filter.FLT_CFG_FL_HTX
    MyFilter.__index = MyFilter

    function MyFilter:new()
        flt = {}
        setmetatable(flt, MyFilter)
        flt.req_len = 0
        flt.res_len = 0
        return flt
     end

    function MyFilter:start_analyze(txn, chn)
        filter.register_data_filter(self, chn)
    end

    function MyFilter:end_analyze(txn, chn)
        print("<Total> request: "..self.req_len.." - response: "..self.res_len)
    end

    function MyFilter:tcp_payload(txn, chn)
        offset = chn:ouput()
	len    = chn:input()
        if chn:is_resp() then
            self.res_len = self.res_len + len
            print("<TCP:Response> offset: "..offset.." - length: "..len)
        else
            self.req_len = self.req_len + len
            print("<TCP:Request> offset: "..offset.." - length: "..len)
        end
    end
2021-08-12 08:57:07 +02:00
Christopher Faulet
a1ac5fb28e MEDIUM: filters/lua: Be prepared to filter TCP payloads
For filters written in lua, the tcp payloads will be filtered using methods
exposed by the Channel class. So the corrsponding C binding functions must
be prepared to process payload in a filter context and not only in an action
context.

The main change is the offset where to start to process data in the channel
buffer, and the length of these data. For an action, all input data are
considered. But for a filter, it depends on what the filter is allow to
forward when the tcp_payload callback function is called. It depends on
previous calls but also on other filters.

In addition, when the payload is modified by a lua filter, its context must
be updated. Note also that channel functions cannot yield when called from a
filter context.

For now, it is not possible to define callbacks to filter data and the
documentation has not been updated.
2021-08-12 08:57:07 +02:00
Christopher Faulet
8c9e6bba0f MINOR: lua: Add flags on the lua TXN to know the execution context
A lua TXN can be created when a sample fetch, an action or a filter callback
function is executed. A flag is now used to track the execute context.
Respectively, HLUA_TXN_SMP_CTX, HLUA_TXN_ACT_CTX and HLUA_TXN_FLT_CTX. The
filter flag is not used for now.
2021-08-12 08:57:07 +02:00
Christopher Faulet
9f55a5012e MINOR: lua: Add a function to get a filter attached to a channel class
For now, there is no support for filters written in lua. So this function,
if called, will always return NULL. But when it will be called in a filter
context, it will return the filter structure attached to a channel
class. This function is also responsible to set the offset of data that may
be processed and the length of these data. When called outside a filter
context (so from an action), the offset is the input data position and the
length is the input data length. From a filter, the offset and the length of
data that may be filtered are retrieved the filter context.
2021-08-12 08:57:07 +02:00
Christopher Faulet
69c581a092 MEDIUM: filters/lua: Add support for dummy filters written in lua
It is now possible to write dummy filters in lua. Only the basis to declare
such filters has been added for now. There is no way to declare callbacks to
filter anything. Lua filters are for now empty nutshells.

To do so, core.register_filter() must be called, with 3 arguments, the
filter's name (as it appears in HAProxy config), the lua class that will be
used to instantiate filters and a function to parse arguments passed on the
filter line in HAProxy configuration file. The lua filter class must at
least define the method new(), without any extra args, to create new
instances when streams are created. If this method is not found, the filter
will be ignored.

Here is a template to declare a new Lua filter:

    // haproxy.conf
    global
        lua-load /path/to/my-filter.lua
        ...

    frontend fe
        ...
        filter lua.my-lua-filter arg1 arg2 arg3
        filter lua.my-lua-filter arg4 arg5

    // my-filter.lua
    MyFilter = {}
    MyFilter.id = "My Lua filter"          -- the filter ID (optional)
    MyFilter.flags = filter.FLT_CFG_FL_HTX -- process HTX streams (optional)
    MyFilter.__index = MyFilter

    function MyFilter:new()
        flt = {}
        setmetatable(flt, MyFilter)
        -- Set any flt fields. self.args can be used
	flt.args = self.args

        return flt -- The new instance of Myfilter
    end

    core.register_filter("my-lua-filter", MyFilter, function(filter, args)
        -- process <args>, an array of strings. For instance:
        filter.args = args
        return filter
    end)

In this example, 2 filters are declared using the same lua class. The
parsing function is called for both, with its own copy of the lua class. So
each filter will be unique.

The global object "filter" exposes some constants and flags, and later some
functions, to help writting filters in lua.

Internally, when a lua filter is instantiated (so when new() method is
called), 2 lua contexts are created, one for the request channel and another
for the response channel. It is a prerequisite to let some callbacks yield
on one side independently on the other one.

There is no documentation for now.
2021-08-12 08:57:07 +02:00
Christopher Faulet
6a79fc16bd MEDIUM: lua: Improve/revisit the lua api to manipulate channels
First of all, following functions are now considered deprecated:

  * Channel:dup()
  * Channel:get()
  * Channel:getline()
  * Channel:get_in_len()
  * Cahnnel:get_out_len()

It is just informative, there is no warning and functions may still be
used. Howver it is recommended to use new functions. New functions are more
flexible and use a better naming pattern. In addition, the same names will
be used in the http_msg class to manipulate http messages from lua filters.

The new API is:

  * Channel:data()
  * Channel:line()
  * Channel:append()
  * Channel:prepend()
  * Channel:insert()
  * Channel:remove()
  * Channel:set()
  * Channel:input()
  * Channel:output()
  * Channel:send()
  * Channel:forward()
  * Channel:is_resp()
  * Channel:is_full()
  * Channel:may_recv()

The lua documentation was updated accordingly.
2021-08-12 08:57:07 +02:00
Christopher Faulet
9a6ffda795 MEDIUM: lua: Process buffer data using an offset and a length
The main change is that following functions will now process channel's data
using an offset and a length:

  * hlua_channel_dup_yield()
  * hlua_channel_get_yield()
  * hlua_channel_getline_yield()
  * hlua_channel_append_yield()
  * hlua_channel_set()
  * hlua_channel_send_yield()
  * hlua_channel_forward_yield()

So for now, the offset is always the input data position and the length is
the input data length. But with the support for filters, from a filter
context, these values will be relative to the filter.

To make all processing clearer, the function _hlua_channel_dup() has been
updated and _hlua_channel_dupline(), _hlua_channel_insert() and
_hlua_channel_delete() have been added.

This patch is mandatory to allow the support of the filters written in lua.
2021-08-12 08:57:07 +02:00
Christopher Faulet
ba9e21dc68 MINOR: lua: Add a function to get a reference on a table in the stack
The hlua_checktable() function may now be used to create and return a
reference on a table in stack, given its position. This function ensures it
is really a table and throws an exception if not.

This patch is mandatory to allow the support of the filters written in lua.
2021-08-12 08:57:07 +02:00
Christopher Faulet
03fb1b26f7 MINOR: filters/lua: Release filters before the lua context
This patch is mandatory to allow the support of the filters written in lua.
2021-08-12 08:57:07 +02:00
Christopher Faulet
23976d9e40 BUG/MINOR: lua: Don't yield in channel.append() and channel.set()
Lua functions to set or append data to the input part of a channel must not
yield because new data may be received while the lua script is suspended. So
adding data to the input part in several passes is highly unpredicatble and
may be interleaved with received data.

Note that if necessary, it is still possible to suspend a lua action by
returning act.YIELD. This way the whole action will be reexecuted later
because of I/O events or a timer. Another solution is to call core.yield().

This bug affects all stable versions. So, it may be backported. But it is
probably not necessary because nobody notice it till now.
2021-08-12 08:57:07 +02:00
Christopher Faulet
2e60aa4dee BUG/MINOR: lua: Yield in channel functions only if lua context can yield
When a script is executed, it is not always allowed to yield. Lua sample
fetches and converters cannot yield. For lua actions, it depends on the
context. When called from tcp content ruleset, an action may yield until the
expiration of the inspect-delay timeout. From http rulesets, yield is not
possible.

Thus, when channel functions (dup, get, append, send...) are called, instead
of yielding when it is not allowed and triggering an error, we just give
up. In this case, some functions do nothing (dup, append...), some others
just interrupt the in-progress job (send, forward...). But, because these
functions don't yield anymore when it is not allowed, the script regains the
control and can continue its execution.

This patch depends on "MINOR: lua: Add a flag on lua context to know the
yield capability at run time". Both may be backported in all stable
versions. However, because nobody notice this bug till now, it is probably
not necessary, excepted if someone ask for it.
2021-08-12 08:57:07 +02:00
Christopher Faulet
1f43a3430e MINOR: lua: Add a flag on lua context to know the yield capability at run time
When a script is executed, a flag is used to allow it to yield. An error is
returned if a lua function yield, explicitly or not. But there is no way to
get this capability in C functions. So there is no way to choose to yield or
not depending on this capability.

To fill this gap, the flag HLUA_NOYIELD is introduced and added on the lua
context if the current script execution is not authorized to yield. Macros
to set, clear and test this flags are also added.

This feature will be usefull to fix some bugs in lua actions execution.
2021-08-12 08:57:07 +02:00
Christopher Faulet
6fcd2d3280 BUG/MINOR: stream: Don't release a stream if FLT_END is still registered
When at least one filter is registered on a stream, the FLT_END analyzer is
called on both direction when all other analyzers have finished their
processing. During this step, filters may release any allocated elements if
necessary. So it is important to not skip it.

Unfortunately, if both stream interfaces are closed, it is possible to not
wait the end of this analyzer. It is possible to be in this situation if a
filter must wait and prevents the analyzer completion. To fix the bug, we
now wait FLT_END analyzer is no longer registered on both direction before
releasing the stream.

This patch may be backported as far as 1.7, but AFAIK, no filter is affected
by this bug. So the backport seems to be optional for now. In any case, it
should remain under observation for some weeks first.
2021-08-12 08:54:16 +02:00
Christopher Faulet
47bfd7b9b7 BUG/MINOR: tcpcheck: Properly detect pending HTTP data in output buffer
In tcpcheck_eval_send(), the condition to detect there are still pending
data in the output buffer is buggy. Presence of raw data must be tested for
TCP connection only. But a condition on the connection was missing to be
sure it is not an HTX connection.

This patch must be backported as far as 2.2.
2021-08-12 07:49:23 +02:00
William Lallemand
7e7765a451 BUG/MINOR: buffer: fix buffer_dump() formatting
The formatting of the buffer_dump() output must be calculated using the
relative counter, not the absolute one, or everything will be broken if
the <from> variable is not a multiple of 16.

Could be backported in all maintained versions.
2021-08-12 00:51:45 +02:00
Amaury Denoyelle
3eb42f91d9 BUG/MEDIUM: server: support both check/agent-check on a dynamic instance
A static server is able to support simultaneously both health chech and
agent-check. Adjust the dynamic server CLI handlers to also support this
configuration.

This should not be backported, unless dynamic server checks are
backported.
2021-08-11 14:41:47 +02:00
Amaury Denoyelle
26cb8342ad BUG/MEDIUM: check: fix leak on agent-check purge
There is currently a leak on agent-check for dynamic servers. When
deleted, the check rules and vars are not liberated. This leak grows
each time a dynamic server with agent-check is deleted.

Replace the manual purge code by a free_check invocation which
centralizes all the details on check cleaning.

There is no leak for health check because in this case the proxy is the
owner of the check vars and rules.

This should not be backported, unless dynamic server checks are
backported.
2021-08-11 14:40:21 +02:00
Amaury Denoyelle
6d7fc446b4 BUG/MINOR: check: fix leak on add dynamic server with agent-check error
If an error occured during a dynamic server creation, free_check is used
to liberate a possible agent-check. However, this does not free
associated vars and rules associated as this is done on another function
named deinit_srv_agent_check.

To simplify the check free and avoid a leak, move free vars/rules in
free_check. This is valid because deinit_srv_agent_check also uses
free_check.

This operation is done only for an agent-check because for a health
check, the proxy instance is the owner of check vars/rules.

This should not be backported, unless dynamic server checks are
backported.
2021-08-11 14:37:42 +02:00
Amaury Denoyelle
25fe1033cb BUG/MINOR: check: do not reset check flags on purge
Do not reset check flags when setting CHK_ST_PURGE.

Currently, this change has no impact. However, it is semantically wrong
to clear important flags such as CHK_ST_AGENT on purge.

Furthermore, this change will become mandatoy for a future fix to
properly free agent checks on dynamic servers removal. For this, it will
be needed to differentiate health/agent-check on purge via CHK_ST_AGENT
to properly free agent checks.

This must not be backported unless dynamic servers checks are
backported.
2021-08-11 14:33:34 +02:00
Amaury Denoyelle
13f2e2ceeb BUG/MINOR: server: do not use refcount in free_server in stopping mode
Currently there is a leak at process shutdown with dynamic servers with
check/agent-check activated. Check purges are not executed on process
stopping, so the server is not liberated due to its refcount.

The solution is simply to ignore the refcount on process stopping mode
and free the server on the first free_server invocation.

This should not be backported, unless dynamic server checks are
backported. In this case, the following commit must be backported first.
  7afa5c1843
  MINOR: global: define MODE_STOPPING
2021-08-09 17:53:30 +02:00
Amaury Denoyelle
7afa5c1843 MINOR: global: define MODE_STOPPING
Define a new mode MODE_STOPPING. It is used to indicate that the process
is in the stopping stage and no event loop runs anymore.
2021-08-09 17:51:55 +02:00
Amaury Denoyelle
9ba34ae710 BUG/MINOR: check: test if server is not null in purge
Test if server is not null before using free_server in the check purge
operation. Currently, the null server scenario should not occured as
purge is used with refcounted dynamic servers. However, this might not
be always the case if purge is use in the future in other cases; thus
the test is useful for extensibility.

No need to backport, unless dynamic server checks are backported.

This has been reported through a coverity report in github issue #1343.
2021-08-09 17:48:34 +02:00
Amaury Denoyelle
b65f4cab6a MEDIUM: server: implement agent check for dynamic servers
This commit is the counterpart for agent check of
"MEDIUM: server: implement check for dynamic servers".

The "agent-check" keyword is enabled for dynamic servers. The agent
check must manually be activated via "enable agent" CLI. This can
enable the dynamic server if the agent response is "ready" without an
explicit "enable server" CLI.
2021-08-06 11:09:48 +02:00
Amaury Denoyelle
2fc4d39577 MEDIUM: server: implement check for dynamic servers
Implement check support for dynamic servers. The "check" keyword is now
enabled for dynamic servers. If used, the server check is initialized
and the check task started in the "add server" CLI handler. The check is
explicitely disabled and must be manually activated via "enable health"
CLI handler.

The dynamic server refcount is incremented if a check is configured. On
"delete server" handler, the check is purged, which decrements the
refcount.
2021-08-06 11:09:48 +02:00
Amaury Denoyelle
9ecee0fa36 MINOR: check: enable safe keywords for dynamic servers
Implement a collection of keywords deemed safe and useful to dynamic
servers. The list of the supported keywords is :
- addr
- check-proto
- check-send-proxy
- check-via-socks4
- rise
- fall
- fastinter
- downinter
- port
- agent-addr
- agent-inter
- agent-port
- agent-send
2021-08-06 11:09:48 +02:00
Amaury Denoyelle
b33a0abc0b MEDIUM: check: implement check deletion for dynamic servers
Implement a mechanism to free a started check on runtime for dynamic
servers. A new function check_purge is created for this. The check task
will be marked for deletion and scheduled to properly close connection
elements and free the task/tasklet/buf_wait elements.

This function will be useful to delete a dynamic server wich checks.
2021-08-06 11:09:48 +02:00
Amaury Denoyelle
d6b7080cec MINOR: server: implement a refcount for dynamic servers
It is necessary to have a refcount mechanism on dynamic servers to be
able to enable check support. Indeed, when deleting a dynamic server
with check activated, the check will be asynchronously removed. This is
mandatory to properly free the check resources in a thread-safe manner.
The server instance must be kept alive for this.
2021-08-06 11:09:48 +02:00
Amaury Denoyelle
403dce8e5a MINOR: check: do not increment global maxsock at runtime
global maxsock is used to estimate a number of fd to reserve for
internal use, such as checks. It is incremented at startup with the info
from the config file.

Disable this incrementation in checks functions at runtime. First, it
currently serves no purpose to increment it after startup. Worse, it may
lead to out-of-bound accesse on the fdtab.

This will be useful to initiate checks for dynamic servers.
2021-08-06 11:08:24 +02:00
Amaury Denoyelle
3c2ab1a0d4 MINOR: check: export check init functions
Remove static qualifier on init_srv_check, init_srv_agent_check and
start_check_task. These functions will be called in server.c for dynamic
servers with checks.
2021-08-06 11:08:04 +02:00
Amaury Denoyelle
f2c27a5c67 MINOR: check: allocate default check ruleset for every backends
Allocate default tcp ruleset for every backend without explicit rules
defined, even if no server in the backend use check. This change is
required to implement checks for dynamic servers.

This allocation is done on check_config_validity. It must absolutely be
called before check_proxy_tcpcheck (called via post proxy check) which
allocate the implicit tcp connect rule.
2021-08-06 11:08:04 +02:00
Amaury Denoyelle
fca18172d9 MINOR: server: initialize fields for dynamic server check
Set default inter/rise/fall values for dynamic servers check/agent. This
is required because dynamic servers do not inherit from a
default-server.
2021-08-06 11:08:04 +02:00
Amaury Denoyelle
7b368339af MEDIUM: task: implement tasklet kill
Implement an equivalent of task_kill for tasklets. This function can be
used to request a tasklet deletion in a thread-safe way.

Currently this function is unused.
2021-08-06 11:07:48 +02:00
Amaury Denoyelle
c755efd5c6 MINOR: server: unmark deprecated on enable health/agent cli
Remove the "DEPRECATED" marker on "enable/disable health/agent"
commands. Their purpose is to toggle the check/agent on a server.

These commands are still useful because their purpose is not covered by
the "set server" command. Most there was confusion with the commands
'set server health/agent', which in fact serves another goal.

Note that the indication "use 'set server' instead" has been added since
2016 on the commit
  2c04eda8b5
  REORG: cli: move "{enable|disable} health" to server.c

and
  58d9cb7d22
  REORG: cli: move "{enable|disable} agent" to server.c

Besides, these commands will become required to enable check/agent on
dynamic servers which will be created with check disabled.

This should be backported up to 2.4.
2021-08-06 10:09:50 +02:00
Christopher Faulet
d7da3dd928 BUG/MEDIUM: spoe: Fix policy to close applets when SPOE connections are queued
It is the second part of the fix that should solve fairness issues with the
connections management inside the SPOE filter. Indeed, in multithreaded
mode, when the SPOE detects there are some connections in queue on a server,
it closes existing connections by releasing SPOE applets. It is mandatory
when a maxconn is set because few connections on a thread may prenvent new
connections establishment.

The first attempt to fix this bug (9e647e5af "BUG/MEDIUM: spoe: Kill applets
if there are pending connections and nbthread > 1") introduced a bug. In
pipelining mode, SPOE applets might be closed while some frames are pending
for the ACK reply. To fix the bug, in the processing stage, if there are
some connections in queue, only truly idle applets may process pending
requests. In this case, only one request at a time is processed. And at the
end of the processing stage, only truly idle applets may be released. It is
an empirical workaround, but it should be good enough to solve contention
issues when a low maxconn is set.

This patch should partely fix the issue #1340. It must be backported as far
as 2.0.
2021-08-05 10:07:43 +02:00
Christopher Faulet
6f1296b5c7 BUG/MEDIUM: spoe: Create a SPOE applet if necessary when the last one is released
On a thread, when the last SPOE applet is released, if there are still
pending streams, a new one is created. Of course, HAproxy must not be
stopping. It is important to start a new applet in this case to not abort
in-progress jobs, especially when a maxconn is set. Because applets may be
closed to be fair with connections waiting for a free slot.

This patch should partely fix the issue #1340. It depends on the commit
"MINOR: spoe: Create a SPOE applet if necessary when the last one on a
thread is closed". Both must be backported as far as 2.0.
2021-08-05 10:07:43 +02:00
Christopher Faulet
434b8525ee MINOR: spoe: Add a pointer on the filter config in the spoe_agent structure
There was no way to access the SPOE filter configuration from the agent
object. However it could be handy to have it. And in fact, this will be
required to fix a bug.
2021-08-05 10:07:43 +02:00
Willy Tarreau
d332f1396b BUG/MINOR: server: update last_change on maint->ready transitions too
Nenad noticed that when leaving maintenance, the servers' last_change
field was not updated. This is visible in the Status column of the stats
page in front of the state, as the cumuled time spent in the current state
is wrong, it starts from the last transition (typically ready->maint). In
addition, the backend's state was not updated either, because the down
transition is performed by set_backend_down() which also emits a log, and
it is this function which was extended to update the backend's last_change,
but it's not called for down->up transitions so that was not done.

The most visible (and unpleasant) effect of this bug is that it affects
slowstart so such a server could immediately restart with a significant
load ratio.

This should likely be backported to all stable releases.
2021-08-04 19:41:01 +02:00
Willy Tarreau
7b2ac29a92 CLEANUP: fd: remove the now unneeded fd_mig_lock
This is not needed anymore since we don't use it when setting the running
mask anymore.
2021-08-04 16:03:36 +02:00
Willy Tarreau
f69fea64e0 MAJOR: fd: get rid of the DWCAS when setting the running_mask
Right now we're using a DWCAS to atomically set the running_mask while
being constrained by the thread_mask. This DWCAS is annoying because we
may seriously need it later when adding support for thread groups, for
checking that the running_mask applies to the correct group.

It turns out that the DWCAS is not strictly necessary because we never
need it to set the thread_mask based on the running_mask, only the other
way around. And in fact, the running_mask is always cleared alone, and
the thread_mask is changed alone as well. The running_mask is only
relevant to indicate a takeover when the thread_mask matches it. Any
bit set in running and not present in thread_mask indicates a transition
in progress.

As such, it is possible to re-arrange this by using a regular CAS around a
consistency check between running_mask and thread_mask in fd_update_events
and by making a CAS on running_mask then an atomic store on the thread_mask
in fd_takeover(). The only other case is fd_delete() but that one already
sets the running_mask before clearing the thread_mask, which is compatible
with the consistency check above.

This change has happily survived 10 billion takeovers on a 16-thread
machine at 800k requests/s.

The fd-migration doc was updated to reflect this change.
2021-08-04 16:03:36 +02:00
Willy Tarreau
b1f29bc625 MINOR: activity/fd: remove the dead_fd counter
This one is set whenever an FD is reported by a poller with a null owner,
regardless of the thread_mask. It has become totally meaningless because
it only indicates a migrated FD that was not yet reassigned to a thread,
but as soon as a thread uses it, the status will change to skip_fd. Thus
there is no reason to distinguish between the two, it adds more confusion
than it helps. Let's simply drop it.
2021-08-04 16:03:36 +02:00
Amaury Denoyelle
bd8dd841e5 BUG/MINOR: server: remove srv from px list on CLI 'add server' error
If an error occured during the CLI 'add server' handler, the newly
created server must be removed from the proxy list if already inserted.
Currently, this can happen on the extremely rare error during server id
generation if there is no id left.

The removal operation is not thread-safe, it must be conducted before
releasing the thread isolation.

This can be backported up to 2.4. Please note that dynamic server track
is not implemented in 2.4, so the release_server_track invocation must
be removed for the backport to prevent a compilation error.
2021-08-04 14:57:06 +02:00
Willy Tarreau
ba3ab7907a MEDIUM: servers: make the server deletion code run under full thread isolation
In 2.4, runtime server deletion was brought by commit e558043e1 ("MINOR:
server: implement delete server cli command"). A comment remained in the
code about a theoretical race between the thread_isolate() call and another
thread being in the process of allocating memory before accessing the
server via a reference that was grabbed before the memory allocation,
since the thread_harmless_now()/thread_harmless_end() pair around mmap()
may have the effect of allowing cli_parse_delete_server() to proceed.

Now that the full thread isolation is available, let's update the code
to rely on this. Now it is guaranteed that competing threads will either
be in the poller or queued in front of thread_isolate_full().

This may be backported to 2.4 if any report of breakage suggests the bug
really exists, in which case the two following patches will also be
needed:
  MINOR: threads: make thread_release() not wait for other ones to complete
  MEDIUM: threads: add a stronger thread_isolate_full() call
2021-08-04 14:49:36 +02:00
Willy Tarreau
88d1c5d3fb MEDIUM: threads: add a stronger thread_isolate_full() call
The current principle of running under isolation was made to access
sensitive data while being certain that no other thread was using them
in parallel, without necessarily having to place locks everywhere. The
main use case are "show sess" and "show fd" which run over long chains
of pointers.

The thread_isolate() call relies on the "harmless" bit that indicates
for a given thread that it's not currently doing such sensitive things,
which is advertised using thread_harmless_now() and which ends usings
thread_harmless_end(), which also waits for possibly concurrent threads
to complete their work if they took this opportunity for starting
something tricky.

As some system calls were notoriously slow (e.g. mmap()), a bunch of
thread_harmless_now() / thread_harmless_end() were placed around them
to let waiting threads do their work while such other threads were not
able to modify memory contents.

But this is not sufficient for performing memory modifications. One such
example is the server deletion code. By modifying memory, it not only
requires that other threads are not playing with it, but are not either
in the process of touching it. The fact that a pool_alloc() or pool_free()
on some structure may call thread_harmless_now() and let another thread
start to release the same object's memory is not acceptable.

This patch introduces the concept of "idle threads". Threads entering
the polling loop are idle, as well as those that are waiting for all
others to become idle via the new function thread_isolate_full(). Once
thread_isolate_full() is granted, the thread is not idle anymore, and
it is released using thread_release() just like regular isolation. Its
users have to keep in mind that across this call nothing is granted as
another thread might have performed shared memory modifications. But
such users are extremely rare and are actually expecting this from their
peers as well.

Note that that in case of backport, this patch depends on previous patch:
  MINOR: threads: make thread_release() not wait for other ones to complete
2021-08-04 14:49:36 +02:00
Willy Tarreau
f519cfaa63 MINOR: threads: make thread_release() not wait for other ones to complete
The original intent of making thread_release() wait for other requesters to
proceed was more of a fairness trade, guaranteeing that a thread that was
granted an access to the CPU would be in turn giving back once its job is
done. But this is counter-productive as it forces such threads to spin
instead of going back to the poller, and it prevents us from implementing
multiple levels of guarantees, as a thread_release() call could spin
waiting for another requester to pass while that requester expects
stronger guarantees than the current thread may be able to offer.

Let's just remove that wait period and let the thread go back to the
poller, a-la "race to idle".

While in theory it could possibly slightly increase the perceived
latency of concurrent slow operations like "show fd" or "show sess",
it is not the case at all in tests, probably because the time needed
to reach the poller remains extremely low anyway.
2021-08-04 14:49:36 +02:00
Willy Tarreau
286363be08 CLEANUP: thread: fix fantaisist indentation of thread_harmless_till_end()
Probably due to a copy-paste, there were two indent levels in this function
since its introduction in 1.9 by commit 60b639ccb ("MEDIUM: hathreads:
implement a more flexible rendez-vous point"). Let's fix this.
2021-08-04 14:49:36 +02:00
Amaury Denoyelle
08be72b827 BUG/MINOR: server: fix race on error path of 'add server' CLI if track
If an error occurs during a dynamic server creation with tracking, it
must be removed from the tracked list. This operation is not thread-safe
and thus must be conducted under the thread isolation.

Track support for dynamic servers has been introduced in this release.
This does not need to be backported.
2021-08-04 09:18:12 +02:00
William Lallemand
85a16b2ba2 MINOR: stats: shows proxy in a stopped state
Previous patch b5c0d65 ("MINOR: proxy: disabled takes a stopping and a
disabled state") allows us to set 2 states for a stopped or a disabled
proxy. With this patch we are now able to show the stats of all proxies
when the process is in a stopping states, not only when there is some
activity on a proxy.

This patch should fix issue #1307.
2021-08-03 14:17:45 +02:00
William Lallemand
8e765b86fd MINOR: proxy: disabled takes a stopping and a disabled state
This patch splits the disabled state of a proxy into a PR_DISABLED and a
PR_STOPPED state.

The first one is set when the proxy is disabled in the configuration
file, and the second one is set upon a stop_proxy().
2021-08-03 14:17:45 +02:00
William Lallemand
56f1f75715 MINOR: log: rename 'dontloglegacyconnerr' to 'log-error-via-logformat'
Rename the 'dontloglegacyconnerr' option to 'log-error-via-logformat'
which is much more self-explanatory and readable.

Note: only legacy keywords don't use hyphens, it is recommended to
separate words with them in new keywords.
2021-08-02 10:42:42 +02:00
Willy Tarreau
55a0975b1e BUG/MINOR: freq_ctr: use stricter barriers between updates and readings
update_freq_ctr_period() was using relaxed atomics without using barriers,
which usually works fine on x86 but not everywhere else. In addition, some
values were read without being enclosed by barriers, allowing the compiler
to possibly prefetch them a bit earlier. Finally, freq_ctr_total() was also
reading these without enough barriers. Let's make explicit use of atomic
loads and atomic stores to get rid of this situation. This required to
slightly rearrange the freq_ctr_total() loop, which could possibly slightly
improve performance under extreme contention by avoiding to reread all
fields.

A backport may be done to 2.4 if a problem is encountered, but last tests
on arm64 with LSE didn't show any issue so this can possibly stay as-is.
2021-08-01 17:34:06 +02:00
Willy Tarreau
200bd50b73 MEDIUM: fd: rely more on fd_update_events() to detect changes
This function already performs a number of checks prior to calling the
IOCB, and detects the change of thread (FD migration). Half of the
controls are still in each poller, and these pollers also maintain
activity counters for various cases.

Note that the unreliable test on thread_mask was removed so that only
the one performed by fd_set_running() is now used, since this one is
reliable.

Let's centralize all that fd-specific logic into the function and make
it return a status among:

  FD_UPDT_DONE,        // update done, nothing else to be done
  FD_UPDT_DEAD,        // FD was already dead, ignore it
  FD_UPDT_CLOSED,      // FD was closed
  FD_UPDT_MIGRATED,    // FD was migrated, ignore it now

Some pollers already used to call it last and have nothing to do after
it, regardless of the result. epoll has to delete the FD in case a
migration is detected. Overall this removes more code than it adds.
2021-07-30 17:45:18 +02:00
Willy Tarreau
84c7922c52 REORG: fd: uninline fd_update_events()
This function has become a monster (80 lines and 2/3 of a kB), it doesn't
benefit from being static nor inline anymore, let's move it to fd.c.
2021-07-30 17:41:55 +02:00
Willy Tarreau
53a16187fd MINOR: poll/epoll: move detection of RDHUP support earlier
Let's move the detection of support for RDHUP earlier and out of the
FD update chain, as it complicates its simplification.
2021-07-30 17:41:55 +02:00
Willy Tarreau
79e90b9615 BUG/MINOR: pollers: always program an update for migrated FDs
If an MT-aware poller reports that a file descriptor was migrated, it
must stop reporting it. The simplest way to do this is to program an
update if not done yet. This will automatically mark the FD for update
on next round. Otherwise there's a risk that some events are reported
a bit too often and cause extra CPU usage with these pollers. Note
that epoll is currently OK regarding this. Select does not need this
because it uses a single shared events table, so in case of migration
no FD change is expected.

This should be backported as far as 2.2.
2021-07-30 14:21:43 +02:00
Willy Tarreau
177119bb11 BUG/MINOR: poll: fix abnormally high skip_fd counter
The skip_fd counter that is incremented when a migrated FD is reported
was abnormally high in with poll. The reason is that it was accounted
for before preparing the polled events instead of being measured from
the reported events.

This mistake was done when the counters were introduced in 1.9 with
commit d80cb4ee1 ("MINOR: global: add some global activity counters to
help debugging"). It may be backported as far as 2.0.
2021-07-30 14:04:28 +02:00
Willy Tarreau
fcc5281513 BUG/MINOR: select: fix excess number of dead/skip reported
In 1.8, commit ab62f5195 ("MINOR: polling: Use fd_update_events to update
events seen for a fd") updated the pollers to rely on fd_update_events(),
but the modification delayed the test of presence of the FD in the report,
resulting in owner/thread_mask and possibly event updates being performed
for each FD appearing in a block of 32 FDs around an active one. This
caused the request rate to be ~3 times lower with select() than poll()
under 6 threads.

This can be backported as far as 1.8.
2021-07-30 13:55:36 +02:00
Willy Tarreau
c37ccd70b4 BUG/MEDIUM: pollers: clear the sleeping bit after waking up, not before
A bug was introduced in 2.1-dev2 by commit 305d5ab46 ("MAJOR: fd: Get
rid of the fd cache."). Pollers "poll" and "evport" had the sleeping
bit accidentally removed before the syscall instead of after. This
results in them not being woken up by inter-thread wakeups, which is
particularly visible with the multi-queue accept() and with queues.

As a work-around, when these pollers are used, "nbthread 1" should
be used.

The fact that it has remained broken for 2 years is a great indication
that threads are definitely not enabled outside of epoll and kqueue,
hence why this patch is only tagged medium.

This must be backported as far as 2.2.
2021-07-30 10:57:09 +02:00
Remi Tricot-Le Breton
4a6328f066 MEDIUM: connection: Add option to disable legacy error log
In case of connection failure, a dedicated error message is output,
following the format described in section "Error log format" of the
documentation. These messages cannot be configured through a log-format
option.
This patch adds a new option, "dontloglegacyconnerr", that disables
those error logs when set, and "replaces" them by a regular log line
that follows the configured log-format (thanks to a call to sess_log in
session_kill_embryonic).
The new fc_conn_err sample fetch allows to add the legacy error log
information into a regular log format.
This new option is unset by default so the logging logic will remain the
same until this new option is used.
2021-07-29 15:40:45 +02:00
Remi Tricot-Le Breton
98b930d043 MINOR: ssl: Define a default https log format
This patch adds a new httpslog option and a new HTTP over SSL log-format
that expands the default HTTP format and adds SSL specific information.
2021-07-29 15:40:45 +02:00
Remi Tricot-Le Breton
7c6898ee49 MINOR: ssl: Add new ssl_fc_hsk_err sample fetch
This new sample fetch along the ssl_fc_hsk_err_str fetch contain the
last SSL error of the error stack that occurred during the SSL
handshake (from the frontend's perspective). The errors happening during
the client's certificate verification will still be given by the
ssl_c_err and ssl_c_ca_err fetches. This new fetch will only hold errors
retrieved by the OpenSSL ERR_get_error function.
2021-07-29 15:40:45 +02:00
Remi Tricot-Le Breton
89b65cfd52 MINOR: ssl: Enable error fetches in case of handshake error
The ssl_c_err, ssl_c_ca_err and ssl_c_ca_err_depth sample fetches values
were not recoverable when the connection failed because of the test
"conn->flags & CO_FL_WAIT_XPRT" (which required the connection to be
established). They could then not be used in a log-format since whenever
they would have sent a non-null value, the value fetching was disabled.
This patch ensures that all these values can be fetched in case of
connection failure.
2021-07-29 15:40:45 +02:00
Remi Tricot-Le Breton
3d2093af9b MINOR: connection: Add a connection error code sample fetch
The fc_conn_err and fc_conn_err_str sample fetches give information
about the problem that made the connection fail. This information would
previously only have been given by the error log messages meaning that
thanks to these fetches, the error log can now be included in a custom
log format. The log strings were all found in the conn_err_code_str
function.
2021-07-29 15:40:45 +02:00
William Lallemand
df9caeb9ae CLEANUP: mworker: PR_CAP already initialized with alloc_new_proxy()
Remove the PR_CAP initialization in mworker_cli_proxy_create() which is
already done in alloc_new_proxy().
2021-07-29 15:35:48 +02:00
William Lallemand
ae787bad80 CLEANUP: mworker: use the proxy helper functions in mworker_cli_proxy_create()
Cleanup the mworker_cli_proxy_create() function by removing the
allocation and init of the proxy which is done manually, and replace it
by alloc_new_proxy(). Do the same with the free_proxy() function.

This patch also move the insertion at the end of the function.
2021-07-29 15:13:22 +02:00
William Lallemand
e7f74623e4 MINOR: stats: don't output internal proxies (PR_CAP_INT)
Disable the output of the statistics of internal proxies (PR_CAP_INT),
wo we don't rely only on the px->uuid > 0. This will allow to hide more
cleanly the internal proxies in the stats.
2021-07-28 17:45:18 +02:00
William Lallemand
d11c5728b4 MINOR: mworker: the mworker CLI proxy is internal
Sets the mworker CLI proxy as a internal one (PR_CAP_INT) so we could
exlude it from stats and other tests.
2021-07-28 17:40:56 +02:00
William Lallemand
6bb77b9c64 MINOR: proxy: rename PR_CAP_LUA to PR_CAP_INT
This patch renames the proxy capability "LUA" to "INT" so it could be
used for any internal proxy.

Every proxy that are not user defined should use this flag.
2021-07-28 15:51:42 +02:00
Christopher Faulet
b5f7b52968 BUG/MEDIUM: mux-h2: Handle remaining read0 cases on partial frames
This part was fixed several times since commit aade4edc1 ("BUG/MEDIUM:
mux-h2: Don't handle pending read0 too early on streams") and there are
still some cases where a read0 event may be ignored because a partial frame
inhibits the event.

Here, we must take care to set H2_CF_END_REACHED flag if a read0 was
received while a partial frame header is received or if the padding length
is missing.

To ease partial frame detection, H2_CF_DEM_SHORT_READ flag is introduced. It
is systematically removed when some data are received and is set when a
partial frame is found or when dbuf buffer is empty. At the end of the
demux, if the connection must be closed ASAP or if data are missing to move
forward, we may acknowledge the pending read0 event, if any. For now,
H2_CF_DEM_SHORT_READ is not part of H2_CF_DEM_BLOCK_ANY mask.

This patch should fix the issue #1328. It must be backported as far as 2.0.
2021-07-27 09:26:02 +02:00
Christopher Faulet
cf30756f0c BUG/MINOR: mux-h1: Be sure to swap H1C to splice mode when rcv_pipe() is called
The splicing does not work anymore because the H1 connection is not swap to
splice mode when rcv_pipe() callback function is called. It is important to
set H1C_F_WANT_SPLICE flag to inhibit data receipt via the buffer
API. Otherwise, because there are always data in the buffer, it is not
possible to use the kernel splicing.

This bug was introduced by the commit 2b861bf72 ("MINOR: mux-h1: clean up
conditions to enabled and disabled splicing").

The patch must be backported to 2.4.
2021-07-26 15:14:35 +02:00
Christopher Faulet
3f35da296e BUG/MINOR: mux-h2: Obey dontlognull option during the preface
If a connection is closed during the preface while no data are received, if
the dontlognull option is set, no log message must be emitted. However, this
will still be handled as a protocol error. Only the log is omitted.

This patch should fix the issue #1336 for H2 sessions. It must be backported
to 2.4 and 2.3 at least, and probably as far as 2.0.
2021-07-26 15:14:35 +02:00
Christopher Faulet
07e10deb36 BUG/MINOR: mux-h1: Obey dontlognull option for empty requests
If a H1 connection is closed while no data are received, if the dontlognull
option is set, no log message must be emitted. Because the H1 multiplexer
handles early errors, it must take care to obey this option. It is true for
400-Bad-Request, 408-Request-Time-out and 501-Not-Implemented
responses. 500-Internal-Server-Error responses are still logged.

This patch should fix the issue #1336 for H1 sessions. It must be backported
to 2.4.
2021-07-26 15:14:35 +02:00
Amaury Denoyelle
2bf5d41ada MINOR: ssl: use __objt_* variant when retrieving counters
Use non-checked function to retrieve listener/server via obj_type. This
is done as a previous obj_type function ensure that the type is well
known and the instance is not NULL.

Incidentally, this should prevent the coverity report from the #1335
github issue which warns about a possible NULL dereference.
2021-07-26 09:59:06 +02:00
Christopher Faulet
1f923391d1 BUG/MINOR: resolvers: Use a null-terminated string to lookup in servers tree
When we evaluate a DNS response item, it may be necessary to look for a
server with a hostname matching the item target into the named servers
tree. To do so, the item target is transformed to a lowercase string. It
must be a null-terminated string. Thus we must explicitly set the trailing
'\0' character.

For a specific resolution, the named servers tree contains all servers using
this resolution with a hostname loaded from a state file. Because of this
bug, same entry may be duplicated because we are unable to find the right
server, assigning this way the item to a free server slot.

This patch should fix the issue #1333. It must be backported as far as 2.2.
2021-07-22 15:03:25 +02:00
Willy Tarreau
b3c4a8f59d BUILD: threads: fix pthread_mutex_unlock when !USE_THREAD
Commit 048368ef6 ("MINOR: deinit: always deinit the init_mutex on
failed initialization") added the missing unlock but forgot to
condition it on USE_THREAD, resulting in a build failure. No
backport is needed.

This addresses oss-fuzz issue 36426.
2021-07-22 14:43:21 +02:00
Willy Tarreau
acff309753 BUG/MINOR: check: fix the condition to validate a port-less server
A config like the below fails to validate because of a bogus test:

  backend b1
      tcp-check connect port 1234
      option tcp-check
      server s1 1.2.3.4 check

[ALERT] (18887) : config : config: proxy 'b1': server 's1' has neither
                  service port nor check port, and a tcp_check rule
                  'connect' with no port information.

A || instead of a && only validates the connect rule when both the
address *and* the port are set. A work around is to set the rule like
this:

      tcp-check connect addr 0:1234 port 1234

This needs to be backported as far as 2.2 (2.0 is OK).
2021-07-22 11:21:33 +02:00
Christopher Faulet
59bab61649 BUG/MINOR: stats: Add missing agent stats on servers
Agent stats were lost during the stats refactoring performed in the 2.4 to
simplify the Prometheus exporter. stats_fill_sv_stats() function must fill
ST_F_AGENT_* and ST_F_LAST_AGT stats.

This patch should fix the issue #1331. It must be backported to 2.4.
2021-07-22 08:47:55 +02:00
Amaury Denoyelle
5fcd428c35 BUG/MEDIUM: ssl_sample: fix segfault for srv samples on invalid request
Some ssl samples cause a segfault when the stream is not instantiated,
for example during an invalid HTTP request. A new check is added to
prevent the stream dereferencing if NULL.

This is the list of the affected samples :
- ssl_s_chain_der
- ssl_s_der
- ssl_s_i_dn
- ssl_s_key_alg
- ssl_s_notafter
- ssl_s_notbefore
- ssl_s_s_dn
- ssl_s_serial
- ssl_s_sha1
- ssl_s_sig_alg
- ssl_s_version

This bug can be reproduced easily by using one of these samples in a
log-format string. Emit an invalid HTTP request with an HTTP client to
trigger the crash.

This bug has been reported in redmine issue 3913.

This must be backported up to 2.2.
2021-07-21 14:23:06 +02:00
Willy Tarreau
3c032f2d4d BUG/MINOR: mworker: do not export HAPROXY_MWORKER_REEXEC across programs
This undocumented variable is only for internal use, and its sole
presence affects the process' behavior, as shown in bug #1324. It must
not be exported to workers, external checks, nor programs. Let's unset
it before forking programs and workers.

This should be backported as far as 1.8. The worker code might differ
a bit before 2.5 due to the recent removal of multi-process support.
2021-07-21 10:17:02 +02:00
Willy Tarreau
26146194d3 BUG/MEDIUM: mworker: do not register an exit handler if exit is expected
The master-worker code registers an exit handler to deal with configuration
issues during reload, leading to a restart of the master process in wait
mode. But it shouldn't do that when it's expected that the program stops
during config parsing or condition checks, as the reload operation is
unexpectedly called and results in abnormal behavior and even crashes:

  $ HAPROXY_MWORKER_REEXEC=1  ./haproxy -W -c -f /dev/null
  Configuration file is valid
  [NOTICE]   (18418) : haproxy version is 2.5-dev2-ee2420-6
  [NOTICE]   (18418) : path to executable is ./haproxy
  [WARNING]  (18418) : config : Reexecuting Master process in waitpid mode
  Segmentation fault

  $ HAPROXY_MWORKER_REEXEC=1 ./haproxy -W -cc 1
  [NOTICE]   (18412) : haproxy version is 2.5-dev2-ee2420-6
  [NOTICE]   (18412) : path to executable is ./haproxy
  [WARNING]  (18412) : config : Reexecuting Master process in waitpid mode
  [WARNING]  (18412) : config : Reexecuting Master process

Note that the presence of this variable happens by accident when haproxy
is called from within its own programs (see issue #1324), but this should
be the object of a separate fix.

This patch fixes this by preventing the atexit registration in such
situations. This should be backported as far as 1.8. MODE_CHECK_CONDITION
has to be dropped for versions prior to 2.5.
2021-07-21 10:01:36 +02:00
Willy Tarreau
dc70c18ddc BUG/MEDIUM: cfgcond: limit recursion level in the condition expression parser
Oss-fuzz reports in issue 36328 that we can recurse too far by passing
extremely deep expressions to the ".if" parser. I thought we were still
limited to the 1024 chars per line, that would be highly sufficient, but
we don't have any limit now :-/

Let's just pass a maximum recursion counter to the recursive parsers.
It's decremented for each call and the expression fails if it reaches
zero. On the most complex paths it can add 3 levels per parenthesis,
so with a limit of 1024, that's roughly 343 nested sub-expressions that
are supported in the worst case. That's more than sufficient, for just
a few kB of RAM.

No backport is needed.
2021-07-20 18:03:08 +02:00
jenny-cheung
048368ef6f MINOR: deinit: always deinit the init_mutex on failed initialization
The init_mutex was not unlocked in case an error is encountered during
a thread initialization, and the polling loop was aborted during startup.
In practise it does not have any observable effect since an explicit
exit() is placed there, but it could confuse some debugging tools or
some static analysers, so let's release it as expected.

This addresses issue #1326.
2021-07-20 16:38:23 +02:00
Christopher Faulet
b73f653d00 CLEANUP: http_ana: Remove now unused label from http_process_request()
Since last change on HTTP analysers (252412316 "MEDIUM: proxy: remove
long-broken 'option http_proxy'"), http_process_request() may only return
internal errors on failures. Thus the label used to handle bad requests may
be removed.

This patch should fix the issue #1330.
2021-07-19 10:32:17 +02:00
Willy Tarreau
252412316e MEDIUM: proxy: remove long-broken 'option http_proxy'
This option had always been broken in HTX, which means that the first
breakage appeared in 1.9, that it was broken by default in 2.0 and that
no workaround existed starting with 2.1. The way this option works is
praticularly unfit to the rest of the configuration and to the internal
architecture. It had some uses when it was introduced 14 years ago but
nowadays it's possible to do much better and more reliable using a
set of "http-request set-dst" and "http-request set-uri" rules, which
additionally are compatible with DNS resolution (via do-resolve) and
are not exclusive to normal load balancing. The "option-http_proxy"
example config file was updated to reflect this.

The option is still parsed so that an error message gives hints about
what to look for.
2021-07-18 19:35:32 +02:00
Willy Tarreau
f1db20c473 BUG/MINOR: cfgcond: revisit the condition freeing mechanism to avoid a leak
The cfg_free_cond_{term,and,expr}() functions used to take a pointer to
the pointer to be freed in order to replace it with a NULL once done.
But this doesn't cope well with freeing lists as it would require
recursion which the current code tried to avoid.

Let's just change the API to free the area and let the caller set the NULL.

This leak was reported by oss-fuzz (issue 36265).
2021-07-17 18:46:30 +02:00
Willy Tarreau
69a23ae091 BUG/MINOR: arg: free all args on make_arg_list()'s error path
While we do free the array containing the arguments, we do not free
allocated ones. Most of them are unresolved, but strings are allocated
and have to be freed as well. Note that for the sake of not breaking
the args resolution list that might have been set, we still refrain
from doing this if a resolution was already programmed, but for most
common cases (including the ones that can be found in config conditions
and at run time) we're safe.

This may be backported to stable branches, but it relies on the new
free_args() function that was introduced by commit ab213a5b6 ("MINOR:
arg: add a free_args() function to free an args array"), and which is
likely safe to backport as well.

This leak was reported by oss-fuzz (issue 36265).
2021-07-17 18:36:43 +02:00
Willy Tarreau
79c9bdf63d BUG/MEDIUM: init: restore behavior of command-line "-m" for memory limitation
The removal for the shared inter-process cache in commit 6fd0450b4
("CLEANUP: shctx: remove the different inter-process locking techniques")
accidentally removed the enforcement of rlimit_memmax_all which
corresponds to what is passed to the command-line "-m" argument.
Let's restore it.

Thanks to @nafets227 for spotting this. This fixes github issue #1319.
2021-07-17 12:31:08 +02:00
Willy Tarreau
316ea7ede5 MINOR: cfgcond: support terms made of parenthesis around expressions
Now it's possible to form a term using parenthesis around an expression.
This will soon allow to build more complex expressions. For now they're
still pretty limited but parenthesis do work.
2021-07-16 19:18:41 +02:00
Willy Tarreau
ca81887599 MINOR: cfgcond: insert an expression between the condition and the term
Now evaluating a condition will rely on an expression (or an empty string),
and this expression will support ORing a sub-expression with another
optional expression. The sub-expressions ANDs a term with another optional
sub-expression. With this alone precedence between && and || is respected,
and the following expression:

     A && B && C || D || E && F || G

will naturally evaluate as:

     (A && B && C) || D || (E && F) || G
2021-07-16 19:18:41 +02:00
Willy Tarreau
087b2d018f MINOR: cfgcond: make the conditional term parser automatically allocate nodes
It's not convenient to let the caller be responsible for node allocation,
better have the leaf function do that and implement the accompanying free
call. Now only a pointer is needed instead of a struct, and the leaf
function makes sure to leave the situation in a consistent way.
2021-07-16 19:18:41 +02:00
Willy Tarreau
ca56d3d28b MINOR: cfgcond: support negating conditional expressions
Now preceeding a config condition term with "!" will simply negate it.
Example:

   .if !feature(OPENSSL)
       .alert "SSL support is mandatory"
   .endif
2021-07-16 19:18:41 +02:00
Willy Tarreau
c8194c30df MINOR: cfgcond: remerge all arguments into a single line
Till now we were dealing with single-word expressions but in order to
extend the configuration condition language a bit more, we'll need to
support slightly more complex expressions involving operators, and we
must absolutely support spaces around them to keep them readable.

As all arguments are pointers to the same line with spaces replaced by
zeroes, we can trivially rebuild the whole line before calling the
condition evaluator, and remove the test for extraneous argument. This
is what this patch does.
2021-07-16 19:18:41 +02:00
Willy Tarreau
379ceeaaeb MEDIUM: cfgcond: report invalid trailing chars after expressions
Random characters placed after a configuration predicate currently do
not report an error. This is a problem because extra parenthesis,
commas or even other random left-over chars may accidently appear there.
Let's now report an error when this happens.

This is marked MEDIUM because it may break otherwise working configs
which are faulty.
2021-07-16 19:18:41 +02:00
Willy Tarreau
f869095df9 MINOR: cfgcond: start to split the condition parser to introduce terms
The purpose is to build a descendent parser that will split conditions
into expressions made of terms. There are two phases, a parsing phase
and an evaluation phase. Strictly speaking it's not required to cut
that in two right now, but it's likely that in the future we won't want
certain predicates to be evaluated during the parsing (e.g. file system
checks or execution of some external commands).

The cfg_eval_condition() function is now much simpler, it just tries to
parse a single term, and if OK evaluates it, then returns the result.
Errors are unchanged and may still be reported during parsing or
evaluation.

It's worth noting that some invalid expressions such as streq(a,b)zzz
continue to parse correctly for now (what remains after the parenthesis
is simply ignored as not necessary).
2021-07-16 19:18:41 +02:00
Willy Tarreau
66243b4273 REORG: config: move the condition preprocessing code to its own file
The .if/.else/.endif and condition evaluation code is quite dirty and
was dumped into cfgparse.c because it was easy. But it should be tidied
quite a bit as it will need to evolve.

Let's move all that to cfgcond.{c,h}.
2021-07-16 19:18:41 +02:00
Willy Tarreau
ee0d727989 CLEANUP: hlua: use free_args() to release args arrays
Argument arrays used in hlua_lua2arg_check() as well as in the functions
used to call sample fetches and converters were manually released, let's
use the cleaner and more reliable free_args() instead. The prototype of
hlua_lua2arg_check() was amended to mention that the function relies on
the final ARGT_STOP, which is already the case, and the pointless test
for this was removed.
2021-07-16 19:18:41 +02:00
Willy Tarreau
c15221b80c CLEANUP: config: use free_args() to release args array in cfg_eval_condition()
Doing so is cleaner than open-coding it and will support future extensions.
2021-07-16 19:18:41 +02:00
Willy Tarreau
ab213a5b6f MINOR: arg: add a free_args() function to free an args array
make_arg_list() can create an array of arguments, some of which remain
to be resolved, but all users had to deal with their own roll back on
error. Let's add a free_args() function to release all the array's
elements and let the caller deal with the array itself (sometimes it's
allocated in the stack).
2021-07-16 19:18:41 +02:00
Willy Tarreau
a87e782a2d MINOR: init: make -cc support environment variables expansion
I found myself a few times testing some conditoin examples from the doc
against command line's "-cc" to see that they didn't work with environment
variables expansion. Not being documented as being on purpose it looks like
a miss, so let's add PARSE_OPT_ENV and PARSE_OPT_WORD_EXPAND to be able to
test for example -cc "streq(${WITH_SSL},yes)" to help debug expressions.
2021-07-16 19:18:41 +02:00
Willy Tarreau
7edc0fde05 MINOR: init: verify that there is a single word on "-cc"
This adds the exact same restriction as commit 5546c8bdc ("MINOR:
cfgparse: Fail when encountering extra arguments in macro") but for
the "-cc" command line argument, for the sake of consistency.
2021-07-16 19:18:41 +02:00
Amaury Denoyelle
56eb8ed37d MEDIUM: server: support track keyword for dynamic servers
Allow the usage of the 'track' keyword for dynamic servers. On server
deletion, the server is properly removed from the tracking chain to
prevents NULL pointer dereferencing.
2021-07-16 10:22:58 +02:00
Amaury Denoyelle
79f68be207 MINOR: srv: do not allow to track a dynamic server
Prevents the use of the "track" keyword for a dynamic server. This
simplifies the deletion of a dynamic server, without having to worry
about servers which might tracked it.

A BUG_ON is present in the dynamic server delete function to validate
this assertion.
2021-07-16 10:08:55 +02:00
Amaury Denoyelle
669b620e5f MINOR: srv: extract tracking server config function
Extract the post-config tracking setup in a dedicated function
srv_apply_track. This will be useful to implement track support for
dynamic servers.
2021-07-16 10:08:55 +02:00
Willy Tarreau
6a51090780 BUILD: lua: silence a build warning with TCC
TCC doesn't have the equivalent of __builtin_unreachable() and complains
that hlua_panic_ljmp() may return no value. Let's add a return 0 there.
All compilers that know that longjmp() doesn't return will see no change
and tcc will be happy.
2021-07-14 19:41:25 +02:00
Willy Tarreau
1335da38f4 BUILD: add detection of missing important CFLAGS
Modern compilers love to break existing code, and some options detected
at build time (such as -fwrapv) are absolutely critical otherwise some
bad code can be generated.

Given that some users rely on packages that force CFLAGS without being
aware of this and can be hit by runtime bugs, we have to help packagers
figure that they need to be careful about their build options.

The test here consists in detecting correct wrapping of signed integers.
Some of the old code relies on it, and modern compilers recently decided
to break it. It's normally addressed using -fwrapv which users will
rarely enforce in their own flags. Thus it is a good indicator of missing
critical CFLAGS, and it happens to be very easy to detect at run time.
Note that the test uses argc in order to have a variable. While gcc
ignores wrapping even for constants, clang only ignores it for variables.
The way the code is constructed doesn't result in code being emitted for
optimized builds thanks to value range propagation.

This should address GitHub issue #1315, and should be backported to all
stable versions. It may result in instantly breaking binaries that seemed
to work fine (typically the ones suddenly showing a busy loop after a few
weeks of uptime), and require packagers to fix their flags. The vast
majority of distro packages are fine and will not be affected though.
2021-07-14 18:50:27 +02:00
Remi Tricot-Le Breton
0498fa4059 BUG/MINOR: ssl: Default-server configuration ignored by server
When a default-server line specified a client certificate to use, the
frontend would not take it into account and create an empty SSL context,
which would raise an error on the backend side ("peer did not return a
certificate").

This bug was introduced by d817dc733e in
which the SSL contexts are created earlier than before (during the
default-server line parsing) without setting it in the corresponding
server structures. It then made the server create an empty SSL context
in ssl_sock_prepare_srv_ctx because it thought it needed one.

It was raised on redmine, in Bug #3906.

It can be backported to 2.4.
2021-07-13 18:35:38 +02:00
Willy Tarreau
4c6986a6bc CLEANUP: applet: remove unused thread_mask
Since 1.9 with commit 673867c35 ("MAJOR: applets: Use tasks, instead
of rolling our own scheduler.") the thread_mask field of the appctx
became unused, but the code hadn't been cleaned for this. The appctx
has its own task and the task's thread_mask is the one to be displayed.

It's worth noting that all calls to appctx_new() pass tid_bit as the
thread_mask. This makes sense, and it could be convenient to decide
that this becomes the norm and to simplify the API.
2021-07-13 18:20:34 +02:00
Amaury Denoyelle
befeae88e8 MINOR: mux_h2: define config to disable h2 websocket support
Define a new global config statement named
"h2-workaround-bogus-websocket-clients".

This statement will disable the automatic announce of h2 websocket
support as specified in the RFC8441. This can be use to overcome clients
which fail to implement the relatively fresh RFC8441. Clients will in
his case automatically downgrade to http/1.1 for the websocket tunnel
if the haproxy configuration allows it.

This feature is relatively simple and can be backported up to 2.4, which
saw the introduction of h2 websocket support.
2021-07-12 10:41:45 +02:00
Amaury Denoyelle
b60fb8d5be BUG/MEDIUM: http_ana: fix crash for http_proxy mode during uri rewrite
Fix the wrong usage of http_uri_parser which is defined with an
uninitialized uri. This causes a crash which happens when forwarding a
request to a backend configured in plain proxy ('option http_proxy').

This has been reported through a clang warning on the CI.

This bug has been introduced by the refactoring of URI parser API.
  c453f9547e
  MINOR: http: use http uri parser for path
This does not need to be backported.

WARNING: although this patch fix the crash, the 'option http_proxy'
seems to be non buggy, possibly since quite a few stable versions.
Indeed, the URI rewriting is not functional : the path is written on the
beginning of the URI but the rest of the URI is not and this garbage is
passed to the server which does not understand the request.
2021-07-08 18:09:52 +02:00
Amaury Denoyelle
c453f9547e MINOR: http: use http uri parser for path
Replace http_get_path by the http_uri_parser API. The new functions is
renamed http_parse_path. Replace duplicated code for scheme and
authority parsing by invocations to http_parse_scheme/authority.

If no scheme is found for an URI detected as an absolute-uri/authority,
consider it to be an authority format : no path will be found. For an
absolute-uri or absolute-path, use the remaining of the string as the
path. A new http_uri_parser state is declared to mark the path parsing
as done.
2021-07-08 17:11:17 +02:00
Amaury Denoyelle
5a9bd375fd REORG: http_ana: split conditions for monitor-uri in wait for request
Split in two the condition which check if the monitor-uri is set for the
current request. This will allow to easily use the http_uri_parser type
for http_get_path.
2021-07-08 17:11:17 +02:00
Amaury Denoyelle
69294b20ac MINOR: http: use http uri parser for authority
Replace http_get_authority by the http_uri_parser API.

The new function is renamed http_parse_authority. Replace duplicated
scheme parsing code by http_parse_scheme invocation. A new
http_uri_parser state is declared to mark the authority parsing as done.
2021-07-08 17:11:17 +02:00
Amaury Denoyelle
8ac8cbfd72 MINOR: http: use http uri parser for scheme
Replace http_get_scheme by the http_uri_parser API. The new function is
renamed http_parse_scheme. A new http_uri_parser state is declared to
mark the scheme parsing as completed.
2021-07-08 17:11:17 +02:00
Amaury Denoyelle
164ae4ad55 BUILD: http_htx: fix ci compilation error with isdigit for Windows
The warning is encountered on platforms for which char type is signed by
default.

cf the following links
https://stackoverflow.com/questions/10186219/array-subscript-has-type-char

This must be backported up to 2.4.
2021-07-07 17:23:57 +02:00
Amaury Denoyelle
4ca0f363a1 MEDIUM: h2: apply scheme-based normalization on h2 requests
Apply the rfc 3986 scheme-based normalization on h2 requests. This
process will be executed for most of requests because scheme and
authority are present on every h2 requests, except CONNECT. However, the
normalization will only be applied on requests with defaults http port
(http/80 or https/443) explicitly specified which most http clients
avoid.

This change is notably useful for http2 websockets with Firefox which
explicitly specify the 443 default port on Extended CONNECT. In this
case, users can be trapped if they are using host routing without
removing the port. With the scheme-based normalization, the default port
will be removed.

To backport this change, it is required to backport first the following
commits:
* MINOR: http: implement http_get_scheme
* MEDIUM: http: implement scheme-based normalization
2021-07-07 15:34:01 +02:00
Amaury Denoyelle
852d78c232 MEDIUM: h1-htx: apply scheme-based normalization on h1 requests
Apply the rfc 3986 scheme-based normalization on h1 requests. It is
executed only for requests which uses absolute-form target URI, which is
not the standard case.
2021-07-07 15:34:01 +02:00
Amaury Denoyelle
4c0882b1b4 MEDIUM: http: implement scheme-based normalization
Implement the scheme-based uri normalization as described in rfc3986
6.3.2. Its purpose is to remove the port of an uri if the default one is
used according to the uri scheme : 80/http and 443/https. All other
ports are not touched.

This method uses an htx message as an input. It requires that the target
URI is in absolute-form with a http/https scheme. This represents most
of h2 requests except CONNECT. On the contrary, most of h1 requests
won't be elligible as origin-form is the standard case.

The normalization is first applied on the target URL of the start line.
Then, it is conducted on every Host headers present, assuming that they
are equivalent to the target URL.

This change will be notably useful to not confuse users who are
accustomed to use the host for routing without specifying default ports.
This problem was recently encountered with Firefox which specify the 443
default port for http2 websocket Extended CONNECT.
2021-07-07 15:34:01 +02:00
Amaury Denoyelle
ef08811240 MINOR: http: implement http_get_scheme
This method can be used to retrieve the scheme part of an uri, with the
suffix '://'. It will be useful to implement scheme-based normalization.
2021-07-07 15:34:01 +02:00
Willy Tarreau
5b654ad42c BUILD: stick-table: shut up invalid "uninitialized" warning in gcc 8.3
gcc 8.3.0 spews a bunch of:

  src/stick_table.c: In function 'action_inc_gpc0':
  include/haproxy/freq_ctr.h:66:12: warning: 'period' may be used uninitialized in this function [-Wmaybe-uninitialized]
    curr_tick += period;
            ^~
  src/stick_table.c:2241:15: note: 'period' was declared here
    unsigned int period;
               ^~~~~~
but they're incorrect because all accesses are guarded by the exact same
condition (ptr1 not being null), it's just the compiler being overzealous
about the uninitialized detection that seems to be stronger than its
ability to follow its own optimizations. This code path is not critical,
let's just pre-initialize the period to zero.

No backport is needed.
2021-07-06 18:54:07 +02:00
Marno Krahmer
07954fb069 MEDIUM: stats: include disabled proxies that hold active sessions to stats
After reloading HAProxy, the old process may still hold active sessions.
Currently there is no way to gather information, how many sessions such
a process still holds. This patch will not exclude disabled proxies from
stats output when they hold at least one active session. This will allow
sending `!@<PID> show stat` through a master socket to the disabled
process and have it returning its stats data.
2021-07-06 11:54:08 +02:00
Christopher Faulet
23048875a4 Revert "MINOR: tcp-act: Add set-src/set-src-port for "tcp-request content" rules"
This reverts commit 19bbbe0562.

For now, set-src/set-src-port actions are directly performed on the client
connection. Using these actions at the stream level is really a problem with
HTTP connection (See #90) because all requests are affected by this change
and not only the current request. And it is worse with the H2, because
several requests can set their source address into the same connection at
the same time.

It is already an issue when these actions are called from "http-request"
rules. It is safer to wait a bit before adding the support to "tcp-request
content" rules. The solution is to be able to set src/dst address on the
stream and not on the connection when the action if performed from the L7
level..

Reverting the above commit means the issue #1303 is no longer fixed.

This patch must be backported in all branches containing the above commit
(as far as 2.0 for now).
2021-07-06 11:44:04 +02:00
Willy Tarreau
dfb34a8f87 BUG/MINOR: cli: fix server name output in "show fd"
A server name was displayed as <srv>/<proxy> instead of the reverse.
It only confuses diagnostics. This was introduced by commit 7a4a0ac71
("MINOR: cli: add a new "show fd" command") so this fix can be backport
down to 1.8.
2021-07-06 11:41:10 +02:00
Willy Tarreau
5a9c637bf3 BUG/MEDIUM: sock: make sure to never miss early connection failures
As shown in issue #1251, it is possible for a connect() to report an
error directly via the poller without ever reporting send readiness,
but currentlt sock_conn_check() manages to ignore that situation,
leading to high CPU usage as poll() wakes up on these FDs.

The bug was apparently introduced in 1.5-dev22 with commit fd803bb4d
("MEDIUM: connection: add check for readiness in I/O handlers"), but
was likely only woken up by recent changes to conn_fd_handler() that
made use of wakeups instead of direct calls between 1.8 and 1.9,
voiding any chance to catch such errors in the early recv() callback.

The exact sequence that leads to this situation remains obscure though
because the poller does not report send readiness nor does it report an
error. Only HUP and IN are reported on the FD. It is also possible that
some recent kernel updates made this condition appear while it never
used to previously.

This needs to be backported to all stable branches, at least as far
as 2.0. Before 2.2 the code was in tcp_connect_probe() in proto_tcp.c.
2021-07-06 10:52:19 +02:00
Emeric Brun
726783db18 MEDIUM: stick-table: make the use of 'gpc' excluding the use of 'gpc0/1''
This patch makes the use of 'gpc' excluding the use of the legacy
types 'gpc0' and 'gpc1" on the same table.

It also makes the use of 'gpc_rate' excluding the use of the legacy
types 'gpc0_rate' and 'gpc1_rate" on the same table.

The 'gpc0' and 'gpc1' related fetches and actions will apply
to the first two elements of the 'gpc' array if stored in table.

The 'gpc0_rate' and 'gpc1_rate' related fetches and actions will apply
to the first two elements of the 'gpc_rate' array if stored in table.
2021-07-06 07:24:42 +02:00
Emeric Brun
4d7ada8f9e MEDIUM: stick-table: add the new arrays of gpc and gpc_rate
This patch adds the definition of two new array data_types:
'gpc': This is an array of 32bits General Purpose Counters.
'gpc_rate': This is an array on increment rates of General Purpose Counters.

Like for all arrays, they are limited to 100 elements.

This patch also adds actions and fetches to handle
elements of those arrays.

Note: As documented, those new actions and fetches won't
apply to the legacy 'gpc0', 'gpc1', 'gpc0_rate' nor 'gpc1_rate'.
2021-07-06 07:24:42 +02:00
Emeric Brun
f7ab0bfb62 MEDIUM: stick-table: make the use of 'gpt' excluding the use of 'gpt0'
This patch makes the use of 'gpt' excluding the use of the legacy
type 'gpt0' on the same table.

It also makes the 'gpt0' related fetches and actions applying
to the first element of the 'gpt' array if stored in table.
2021-07-06 07:24:42 +02:00
Emeric Brun
877b0b5a7b MEDIUM: stick-table: add the new array of gpt data_type
This patch adds the definition of a new array data_type
'gpt'. This is an array of 32bits General Purpose Tags.

Like for all arrays, it is limited to 100 elements.

This patch also adds actions and fetches to handle
elements of this array.

Note: As documented, those new actions and fetches won't
apply to the legacy 'gpt0' data type.
2021-07-06 07:24:42 +02:00
Emeric Brun
90a9b676a8 MEDIUM: peers: handle arrays of std types in peers protocol
This patch adds support of array data_types on the peer protocol.

The table definition message will provide an additionnal parameter
for array data-types: the number of elements of the array.

In case of array of frqp it also provides a second parameter:
the period used to compute freq counter.

The array elements are std_type values linearly encoded in
the update message.

Note: if a remote peer announces an array data_type without
parameters into the table definition message, all updates
on this table will be ignored because we can not
parse update messages consistently.
2021-07-06 07:24:42 +02:00
Emeric Brun
c64a2a307c MEDIUM: stick-table: handle arrays of standard types into stick-tables
This patch provides the code to handle arrays of some
standard types (SINT, UINT, ULL and FRQP) in stick table.

This way we could define new "array" data types.

Note: the number of elements of an array was limited
to 100 to put a limit and to ensure that an encoded
update message will continue to fit into a buffer
when the peer protocol will handle such data types.
2021-07-06 07:24:42 +02:00
Emeric Brun
0e3457b63a MINOR: stick-table: make skttable_data_cast to use only std types
This patch replaces all advanced data type aliases on
stktable_data_cast calls by standard types.

This way we could call the same stktable_data_cast
regardless of the used advanced data type as long they
are using the same std type.

It also removes all the advanced data type aliases.
2021-07-06 07:24:42 +02:00
Emeric Brun
08b0f6780c BUG/MINOR: peers: fix data_type bit computation more than 32 data_types
This patch fixes the computation of the bit of the current data_type
in some part of code of peer protocol where the computation is limited
to 32bits whereas the bitfield of data_types can support 64bits.

Without this patch it could result in bugs when we will define more
than 32 data_types.

Backport is useless because there is currently less than 32 data_types
2021-07-06 07:24:42 +02:00
Emeric Brun
01928ae56b BUG/MINOR: stick-table: fix several printf sign errors dumping tables
This patch fixes several errors printing integers
of stick table entry values and args during dump on cli.

This patch should be backported since the dump of entries
is supported.  [wt: roughly 1.5-dev1 hence all stable branches]
2021-07-06 07:24:42 +02:00
David Carlier
bae4cb2790 BUILD/MEDIUM: tcp: set-mark support for OpenBSD
set-mark support for this platform, for routing table purpose.
Follow-up from f7f53afcf9, this time for OpenBSD.
2021-07-05 10:53:18 +02:00
Emeric Brun
5ea07d9e91 CLEANUP: peers: re-write intdecode function comment.
The varint decoding function comment was not clear enough and
didn't reflect the current usage.

This patch re-writes this.
2021-06-30 13:49:12 +02:00
Christopher Faulet
81ba74ae50 BUG/MEDIUM: resolvers: Make 1st server of a template take part to SRV resolution
The commit 3406766d5 ("MEDIUM: resolvers: add a ref between servers and srv
request or used SRV record") introduced a regression. The first server of a
template based on SRV record is no longer resolved. The same bug exists for
a normal server based on a SRV record.

In fact, the server used during parsing (used as reference when a
server-template line is parsed) is never attached to the corresponding srvrq
object. Thus with following lines, no resolution is performed because
"srvrq->attached_servers" is empty:

  server-template test 1 _http.domain.tld resolvers dns ...
  server test1 _http.domain.tld resolvers dns ...

This patch should fix the issue #1295 (but not confirmed yet it is the same
bug). It must be backported everywhere the above commit is.
2021-06-29 20:52:37 +02:00
Christopher Faulet
0de0becf0b BUG/MINOR: mqtt: Support empty client ID in CONNECT message
As specified by the MQTT specification (MQTT-3.1.3-6), the client ID may be
empty. That means the length of the client ID string may be 0. However, The
MQTT parser does not support empty strings.

So, to fix the bug, the mqtt_read_string() function may now parse empty
string. 2 bytes must be found to decode the string length, but the length
may be 0 now. It is the caller responsibility to test the string emptiness
if necessary. In addition, in mqtt_parse_connect(), the client ID may be
empty now.

This patch should partely fix the issue #1310. It must be backported to 2.4.
2021-06-28 16:29:44 +02:00
Christopher Faulet
ca925c9c28 BUG/MINOR: mqtt: Fix parser for string with more than 127 characters
Parsing of too long strings (> 127 characters) was buggy because of a wrong
cast on the length bytes. To fix the bug, we rely on mqtt_read_2byte_int()
function. This way, the string length is properly decoded.

This patch should partely fix the issue #1310. It must be backported to 2.4.
2021-06-28 16:29:44 +02:00
Willy Tarreau
5bbfff107b BUILD: tcp-act: avoid warning when set-mark / set-tos are not supported
Since recent commit 469c06c30 ("MINOR: http-act/tcp-act: Add "set-mark"
and "set-tos" for tcp content rules") there's a build warning (or error)
on Windows due to static function tcp_action_set_mark() not being used
because the set-mark functionality is not supported there. It's caused
by the fact that only the parsing function uses it so if the code is
ifdefed out the function remains unused.

Let's surround it with ifdefs as well, and do the same for
tcp_action_set_tos() which could suffer the same fate on operating systems
not defining IP_TOS.

This may need to be backported if the patch above is backported. Also
be careful, the condition was adjusted to cover FreeBSD after commit
f7f53afcf ("BUILD/MEDIUM: tcp: set-mark setting support for FreeBSD.").
2021-06-28 07:12:22 +02:00
David Carlier
f7f53afcf9 BUILD/MEDIUM: tcp: set-mark setting support for FreeBSD.
This platform has a similar socket option from Linux's SO_MARK,
marking a socket with an id for packet filter purpose, DTrace
monitoring and so on.
2021-06-28 07:03:35 +02:00
Christopher Faulet
ee9c98d81b CLEANUP: tcp-act: Sort action lists
Sort the lists used to register tcp actions.
2021-06-25 16:12:02 +02:00
Christopher Faulet
469c06c30e MINOR: http-act/tcp-act: Add "set-mark" and "set-tos" for tcp content rules
It is now possible to set the Netfilter MARK and the TOS field value in all
packets sent to the client from any tcp-request rulesets or the "tcp-response
content" one. To do so, the parsing of "set-mark" and "set-tos" actions are
moved in tcp_act.c and the actions evaluation is handled in dedicated functions.

This patch may be backported as far as 2.2 if necessary.
2021-06-25 16:11:58 +02:00
Christopher Faulet
1da374af2f MINOR: http-act/tcp-act: Add "set-nice" for tcp content rules
It is now possible to set the "nice" factor of the current stream from a
"tcp-request content" or "tcp-response content" ruleset. To do so, the
action parsing is moved in stream.c and the action evaluation is handled in
a dedicated function.

This patch may be backported as far as 2.2 if necessary.
2021-06-25 16:11:53 +02:00
Christopher Faulet
551a641cff MINOR: http-act/tcp-act: Add "set-log-level" for tcp content rules
It is now possible to set the stream log level from a "tcp-request content"
or "tcp-response content" ruleset. To do so, the action parsing is moved in
stream.c and the action evaluation is handled in a dedicated function.

This patch should fix issue #1306. It may be backported as far as 2.2 if
necessary.
2021-06-25 16:11:46 +02:00
Christopher Faulet
fa5880bd53 BUG/MINOR: tcpcheck: Fix numbering of implicit HTTP send/expect rules
The index of the failing rule is reported in the health-check log message. The
rules index is also used in the check traces. But for implicit HTTP send/expect
rules, the index is wrong. It must be incremented by one compared to the
preceding rule.

This patch may be backported as far as 2.2.
2021-06-25 14:03:45 +02:00
Dirkjan Bussink
dfee217b68 BUG/MINOR: checks: return correct error code for srv_parse_agent_check
In srv_parse_agent_check the error code is not returned in case
something goes wrong. The value 0 is always return.

Additionally, there's a small cleanup of unreachable returns that in
most checks are not present either and removed in two places they were
present. This makes the code consistent across the different checks.
2021-06-25 08:55:39 +02:00
Christopher Faulet
07ecff589d MINOR: resolvers: Reset server IP on error in resolv_get_ip_from_response()
If resolv_get_ip_from_response() returns an error (or an unexpected return
value), the server is set to RMAINT status. However, its address must also
be reset. Otherwise, it is still reported by the cli on "show servers state"
commands. This may be confusing. Note that it is a theorical patch because
this code path does not exist. Thus it is not tagged as a BUG.

This patch may be backported as far as 2.0.
2021-06-24 17:22:36 +02:00
Christopher Faulet
a8ce497aac BUG/MINOR: resolvers: Reset server IP when no ip is found in the response
For A/AAAA resolution, if no ip is found for a server in the response, the
server is set to RMAINT status. However, its address must also be
reset. Otherwise, it is still reported by the cli on "show servers state"
commands. This may be confusing.

This patch may be backported as far as 2.0.
2021-06-24 17:22:36 +02:00
Christopher Faulet
d7bb23490c BUG/MINOR: resolvers: Always attach server on matching record on resolution
On A/AAAA resolution, for a given server, if a record is matching, we must
always attach the server to this record. Before it was only done if the
server IP was not the same than the record one. However, it is a problem if
the server IP was not set for a previous resolution. From the libc during
startup for instance. In this case, the server IP is not updated and the
server is not attached to any record. It remains in this state while a
matching record is found in the DNS response. It is especially a problem
when the resolution is used for server-templates.

This bug was introduced by the commit bd78c912f ("MEDIUM: resolvers: add a
ref on server to the used A/AAAA answer item").

This patch should solve the issue #1305. It must be backported to all
versions containing the above commit.
2021-06-24 17:15:33 +02:00
Willy Tarreau
47ee44fb71 BUG/MINOR: queue/debug: use the correct lock labels on the queue lock
A dedicated queue lock was added by commit 16fbdda3c ("MEDIUM: queue:
use a dedicated lock for the queues (v2)") but during its rebase, some
labels were lost and left to SERVER_LOCK / PROXY_LOCK instead of
QUEUE_LOCK. It's harmless but can confuse the lock debugger, so better
fix it.

No backport is needed.
2021-06-24 16:00:18 +02:00
Willy Tarreau
19c5581b43 BUG: backend: stop looking for queued connections once there's no more
Commit ae0b12ee0 ("MEDIUM: queue: use a trylock on the server's queue")
introduced a hard to trigger bug that's more visible with a single thread:
if a server dequeues a connection and finds another free slot with no
connection to place there, process_srv_queue() will never break out of
the loop. In multi-thread it almost does not happen because other threads
bring new connections.

No backport is needed as it's only in -dev.
2021-06-24 15:56:07 +02:00
Willy Tarreau
d03adce575 MINOR: queue: simplify pendconn_unlink() regarding srv vs px
Since the code paths became exactly the same except for what log field
to update, let's simplify the code and move further code out of the
lock. The queue position update and the test for server vs proxy do not
need to be inside the lock.
2021-06-24 10:52:31 +02:00
Willy Tarreau
51c63f0f0a MINOR: queue: remove the px/srv fields from pendconn
Now we directly use p->queue to get to the queue, which is much more
straightforward. The performance on 100 servers and 16 threads
increased from 560k to 574k RPS, or 2.5%.

A lot more simplifications are possible, but the minimum was done at
this point.
2021-06-24 10:52:31 +02:00
Willy Tarreau
8429097c61 MINOR: queue: store a pointer to the queue into the pendconn
By following the queue pointer in the pendconn it will now be possible
to always retrieve the elements (index, srv, px, etc).
2021-06-24 10:52:31 +02:00
Willy Tarreau
cdc83e0192 MINOR: queue: add a pointer to the server and the proxy in the queue
A queue is specific to a server or a proxy, so we don't need to place
this distinction inside all pendconns, it can be in the queue itself.
This commit adds the relevant fields "px" and "sv" into the struct
queue, and initializes them accordingly.
2021-06-24 10:52:31 +02:00
Willy Tarreau
df3b0cbe31 MINOR: queue: add queue_init() to initialize a queue
This is better and cleaner than open-coding this in the server and
proxy code, where it has all chances of becoming wrong once forgotten.
2021-06-24 10:52:31 +02:00
Willy Tarreau
ae0b12ee03 MEDIUM: queue: use a trylock on the server's queue
Doing so makes sure that threads attempting to wake up new connections
for a server will give up early if another thread is already in charge
of this. The goal is to avoid unneeded contention on low server counts.

Now with a single server with 16 threads in roundrobin we get the same
performance as with multiple servers, i.e. ~575kreq/s instead of ~496k
before. Leastconn is seeing a similar jump, from ~460 to ~560k (the
difference being the calls to fwlc_srv_reposition).

The overhead of process_srv_queue() is now around 2% instead of ~20%
previously.
2021-06-24 10:52:31 +02:00
Willy Tarreau
49667c14ba MEDIUM: queue: take the proxy lock only during the px queue accesses
There's no point keeping the proxy lock held for a long time, it's
only needed when checking the proxy's queue, and keeping it prevents
multiple servers from dequeuing in parallel. Let's move it into
pendconn_process_next_strm() and release it ASAP. The pendconn
remains under the server queue lock's protection, guaranteeing that
no stream will release it while it's being touched.

For roundrobin, the performance increases by 76% (327k to 575k) on
16 threads. Even with a single server and maxconn=100, the performance
increases from 398 to 496 kreq/s. For leastconn, almost no change is
visible (less than one percent) but this is expected since most of the
time there is spent in fwlc_reposition() and fwlc_get_next_server().
2021-06-24 10:52:31 +02:00
Willy Tarreau
98c8910be7 MINOR: queue: use atomic-ops to update the queue's index (v2)
Doing so allows to retrieve and update the pendconn's queue index outside
of the queue's lock and to save one more percent CPU on a highly-contented
backend.
2021-06-24 10:52:31 +02:00
Willy Tarreau
12529c0ed3 MINOR: queue: factor out the proxy/server queuing code (v2)
The code only differed by the nbpend_max counter. Let's have a pointer
to it and merge the two variants to always use a generic queue. It was
initially considered to put the max inside the queue structure itself,
but the stats support clearing values and maxes and this would have been
the only counter having to be handled separately there. Given that we
don't need this max anywhere outside stats, let's keep it where it is
and have a pointer to it instead.

The CAS loop to update the max remains. It was naively thought that it
would have been faster without atomic ops inside the lock, but this is
not the case for the simple reason that it is a max, it converges very
quickly and never has to perform the check anymore. Thus this code is
better out of the lock.

The queue_idx is still updated inside the lock since that's where the
idx is updated, though it could be performed using atomic ops given
that it's only used to roughly count places for logging.
2021-06-24 10:52:31 +02:00
Willy Tarreau
a0e9c55ab1 MEDIUM: queue: determine in process_srv_queue() if the proxy is usable (v2)
By doing so we can move some evaluations outside of the lock and the
loop.
2021-06-24 10:52:31 +02:00
Willy Tarreau
9ab78293bf MEDIUM: queue: simplify again the process_srv_queue() API (v2)
This basically undoes the API changes that were performed by commit
0274286dd ("BUG/MAJOR: server: fix deadlock when changing maxconn via
agent-check") to address the deadlock issue: since process_srv_queue()
doesn't use the server lock anymore, it doesn't need the "server_locked"
argument, so let's get rid of it before it gets used again.
2021-06-24 10:52:31 +02:00
Willy Tarreau
16fbdda3c3 MEDIUM: queue: use a dedicated lock for the queues (v2)
Till now whenever a server or proxy's queue was touched, this server
or proxy's lock was taken. Not only this requires distinct code paths,
but it also causes unnecessary contention with other uses of these locks.

This patch adds a lock inside the "queue" structure that will be used
the same way by the server and the proxy queuing code. The server used
to use a spinlock and the proxy an rwlock, though the queue only used
it for locked writes. This new version uses a spinlock since we don't
need the read lock part here. Tests have not shown any benefit nor cost
in using this one versus the rwlock so we could change later if needed.

The lower contention on the locks increases the performance from 362k
to 374k req/s on 16 threads with 20 servers and leastconn. The gain
with roundrobin even increases by 9%.

This is tagged medium because the lock is changed, but no other part of
the code touches the queues, with nor without locking, so this should
remain invisible.
2021-06-24 10:52:31 +02:00
Willy Tarreau
9cef43acab MEDIUM: queue: update px->served and lb's take_conn once per loop
There's no point doing atomic incs over px->served/px->totpend under the
locks from the inner loop, as this value is used by the LB algorithms but
not during the dequeuing step. In addition, the LB algo's take_conn()
doesn't need to be refreshed for each and every connection taken
under the lock, it can be performed once at the end and out of the
lock.

While the gain on roundrobin is not noticeable (only the atomic inc),
on leastconn which uses take_conn(), the performance increases from
355k to 362k req/s on 16 threads.
2021-06-24 10:09:40 +02:00
Willy Tarreau
a48905bad8 Revert "MEDIUM: queue: make pendconn_process_next_strm() only return the pendconn"
This reverts commit 5304669e1b.

The recent changes since 5304669e1 MEDIUM: queue: make
pendconn_process_next_strm() only return the pendconn opened a tiny race
condition between stream_free() and process_srv_queue(), as the pendconn
is accessed outside of the lock, possibly while it's being freed. A
different approach is required.
2021-06-24 09:55:59 +02:00
Willy Tarreau
d83c98eb14 Revert "MINOR: queue: update proxy->served once out of the loop"
This reverts commit 3e92a31783.

The recent changes since 5304669e1 MEDIUM: queue: make
pendconn_process_next_strm() only return the pendconn opened a tiny race
condition between stream_free() and process_srv_queue(), as the pendconn
is accessed outside of the lock, possibly while it's being freed. A
different approach is required.
2021-06-24 09:55:14 +02:00
Willy Tarreau
e76fc3253d Revert "MEDIUM: queue: refine the locking in process_srv_queue()"
This reverts commit 1b648c857b.

The recent changes since 5304669e1 MEDIUM: queue: make
pendconn_process_next_strm() only return the pendconn opened a tiny race
condition between stream_free() and process_srv_queue(), as the pendconn
is accessed outside of the lock, possibly while it's being freed. A
different approach is required.
2021-06-24 09:55:14 +02:00
Willy Tarreau
3f70fb9ea2 Revert "MEDIUM: queue: use a dedicated lock for the queues"
This reverts commit fcb8bf8650.

The recent changes since 5304669e1 MEDIUM: queue: make
pendconn_process_next_strm() only return the pendconn opened a tiny race
condition between stream_free() and process_srv_queue(), as the pendconn
is accessed outside of the lock, possibly while it's being freed. A
different approach is required.
2021-06-24 07:26:28 +02:00
Willy Tarreau
ccd85a3e08 Revert "MEDIUM: queue: simplify again the process_srv_queue() API"
This reverts commit c83e45e9b0.

The recent changes since 5304669e1 MEDIUM: queue: make
pendconn_process_next_strm() only return the pendconn opened a tiny race
condition between stream_free() and process_srv_queue(), as the pendconn
is accessed outside of the lock, possibly while it's being freed. A
different approach is required.
2021-06-24 07:22:18 +02:00
Willy Tarreau
58f4dfb2b0 Revert "MINOR: queue: factor out the proxy/server queuing code"
This reverts commit 3eecdb65c5.

The recent changes since 5304669e1 MEDIUM: queue: make
pendconn_process_next_strm() only return the pendconn opened a tiny race
condition between stream_free() and process_srv_queue(), as the pendconn
is accessed outside of the lock, possibly while it's being freed. A
different approach is required.
2021-06-24 07:22:15 +02:00
Willy Tarreau
a4a9bbadc6 Revert "MINOR: queue: use atomic-ops to update the queue's index"
This reverts commit 1335eb9867.

The recent changes since 5304669e1 MEDIUM: queue: make
pendconn_process_next_strm() only return the pendconn opened a tiny race
condition between stream_free() and process_srv_queue(), as the pendconn
is accessed outside of the lock, possibly while it's being freed. A
different approach is required.
2021-06-24 07:22:12 +02:00
Willy Tarreau
ddac4a1f35 Revert "MEDIUM: queue: determine in process_srv_queue() if the proxy is usable"
This reverts commit de814dd422.

The recent changes since 5304669e1 MEDIUM: queue: make
pendconn_process_next_strm() only return the pendconn opened a tiny race
condition between stream_free() and process_srv_queue(), as the pendconn
is accessed outside of the lock, possibly while it's being freed. A
different approach is required.
2021-06-24 07:22:08 +02:00
Willy Tarreau
5343d8ed6f Revert "MEDIUM: queue: move the queue lock manipulation to pendconn_process_next_strm()"
This reverts commit 9a6d0ddbd6.

The recent changes since 5304669e1 MEDIUM: queue: make
pendconn_process_next_strm() only return the pendconn opened a tiny race
condition between stream_free() and process_srv_queue(), as the pendconn
is accessed outside of the lock, possibly while it's being freed. A
different approach is required.
2021-06-24 07:22:03 +02:00
Willy Tarreau
90a160a465 Revert "MEDIUM: queue: unlock as soon as possible"
This reverts commit 5b39275311.

The recent changes since 5304669e1 MEDIUM: queue: make
pendconn_process_next_strm() only return the pendconn opened a tiny race
condition between stream_free() and process_srv_queue(), as the pendconn
is accessed outside of the lock, possibly while it's being freed. A
different approach is required.
2021-06-24 07:21:59 +02:00
Willy Tarreau
2bf3f2cf7f Revert "MINOR: queue: make pendconn_first() take the lock by itself"
This reverts commit 772e968b06.

The recent changes since 5304669e1 MEDIUM: queue: make
pendconn_process_next_strm() only return the pendconn opened a tiny race
condition between stream_free() and process_srv_queue(), as the pendconn
is accessed outside of the lock, possibly while it's being freed. A
different approach is required.
2021-06-24 07:20:26 +02:00
Christopher Faulet
c3fe968f22 CLEANUP: dns: Remove a forgotten debug message
A debug message was forgotten in the dns part.

This patch should fix the issue #1304. It must be backported to 2.4.
2021-06-23 12:21:47 +02:00
Christopher Faulet
19bbbe0562 MINOR: tcp-act: Add set-src/set-src-port for "tcp-request content" rules
If it possible to set source IP/Port from "tcp-request connection",
"tcp-request session" and "http-request" rules but not from "tcp-request
content" rules. There is no reason for this limitation and it may be a
problem for anyone wanting to call a lua fetch to dynamically set source
IP/Port from a TCP proxy. Indeed, to call a lua fetch, we must have a
stream. And there is no stream when "tcp-request connection/session" rules
are evaluated.

Thanks to this patch, "set-src" and "set-src-port" action are now supported
by "tcp_request content" rules.

This patch is related to the issue #1303. It may be backported to all stable
versions.
2021-06-23 12:07:24 +02:00
Willy Tarreau
5ffb045ed1 CLEANUP: backend: remove impossible case of round-robin + consistent hash
In 1.4, consistent hashing was brought by commit 6b2e11be1 ("[MEDIUM]
backend: implement consistent hashing variation") which took care of
replacing all direct calls to map_get_server_rr() with an alternate
call to chash_get_next_server() if consistent hash was being used.

One of them, however, cannot happen because a preliminary test for
static round-robin is being done prior to the call, so we're certain
that if it matches it cannot use a consistent hash tree.

Let's remove it.
2021-06-22 19:21:11 +02:00
Willy Tarreau
772e968b06 MINOR: queue: make pendconn_first() take the lock by itself
Dealing with the queue lock in the caller remains complicated. Let's
change pendconn_first() to take the queue instead of the tree head,
and handle the lock itself. It now returns an element with a locked
queue or no element with an unlocked queue. It can avoid locking if
the queue is already empty.
2021-06-22 18:57:18 +02:00
Willy Tarreau
5b39275311 MEDIUM: queue: unlock as soon as possible
There's no point keeping the server's queue lock after seeing that the
server's queue is empty, just like there's no need to keep the proxy's
lock when its queue is empty. This patch checks for emptiness and
releases these locks as soon as possible.

With this the performance increased from 524k to 530k on 16 threads
with round-robin.
2021-06-22 18:57:18 +02:00
Willy Tarreau
9a6d0ddbd6 MEDIUM: queue: move the queue lock manipulation to pendconn_process_next_strm()
By placing the lock there, it becomes possible to lock the proxy
later and to unlock it earlier. The server unlocking also happens slightly
earlier.

The performance on roundrobin increases from 481k to 524k req/s on 16
threads. Leastconn shows about 513k req/s (the difference being the
take_conn() call).

The performance profile changes from this:
   9.32%  hap-pxok            [.] process_srv_queue
   7.56%  hap-pxok            [.] pendconn_dequeue
   6.90%  hap-pxok            [.] pendconn_add

to this:
   7.42%  haproxy             [.] process_srv_queue
   5.61%  haproxy             [.] pendconn_dequeue
   4.95%  haproxy             [.] pendconn_add
2021-06-22 18:57:18 +02:00
Willy Tarreau
de814dd422 MEDIUM: queue: determine in process_srv_queue() if the proxy is usable
By doing so we can move some evaluations outside of the lock and the
loop. In the round robin case, the performance increases from 497k to
505k rps on 16 threads with 100 servers.
2021-06-22 18:57:18 +02:00
Willy Tarreau
1335eb9867 MINOR: queue: use atomic-ops to update the queue's index
Doing so allows to retrieve and update the pendconn's queue index outside
of the queue's lock and to save one more percent CPU on a highly-contented
backend.
2021-06-22 18:57:18 +02:00
Willy Tarreau
3eecdb65c5 MINOR: queue: factor out the proxy/server queuing code
The code only differed by the nbpend_max counter. Let's have a pointer
to it and merge the two variants to always use a generic queue. It was
initially considered to put the max inside the queue structure itself,
but the stats support clearing values and maxes and this would have been
the only counter having to be handled separately there. Given that we
don't need this max anywhere outside stats, let's keep it where it is
and have a pointer to it instead.

The CAS loop to update the max remains. It was naively thought that it
would have been faster without atomic ops inside the lock, but this is
not the case for the simple reason that it is a max, it converges very
quickly and never has to perform the check anymore. Thus this code is
better out of the lock.

The queue_idx is still updated inside the lock since that's where the
idx is updated, though it could be performed using atomic ops given
that it's only used to roughly count places for logging.
2021-06-22 18:57:18 +02:00
Willy Tarreau
c83e45e9b0 MEDIUM: queue: simplify again the process_srv_queue() API
This basically undoes the API changes that were performed by commit
0274286dd ("BUG/MAJOR: server: fix deadlock when changing maxconn via
agent-check") to address the deadlock issue: since process_srv_queue()
doesn't use the server lock anymore, it doesn't need the "server_locked"
argument, so let's get rid of it before it gets used again.
2021-06-22 18:57:15 +02:00
Willy Tarreau
fcb8bf8650 MEDIUM: queue: use a dedicated lock for the queues
Till now whenever a server or proxy's queue was touched, this server
or proxy's lock was taken. Not only this requires distinct code paths,
but it also causes unnecessary contention with other uses of these locks.

This patch adds a lock inside the "queue" structure that will be used
the same way by the server and the proxy queuing code. The server used
to use a spinlock and the proxy an rwlock, though the queue only used
it for locked writes. This new version uses a spinlock since we don't
need the read lock part here. Tests have not shown any benefit nor cost
in using this one versus the rwlock so we could change later if needed.

The lower contention on the locks increases the performance from 491k
to 507k req/s on 16 threads with 20 servers and leastconn. The gain
with roundrobin even increases by 6%.

The performance profile changes from this:
  13.03%  haproxy             [.] fwlc_srv_reposition
   8.08%  haproxy             [.] fwlc_get_next_server
   3.62%  haproxy             [.] process_srv_queue
   1.78%  haproxy             [.] pendconn_dequeue
   1.74%  haproxy             [.] pendconn_add

to this:
  11.95%  haproxy             [.] fwlc_srv_reposition
   7.57%  haproxy             [.] fwlc_get_next_server
   3.51%  haproxy             [.] process_srv_queue
   1.74%  haproxy             [.] pendconn_dequeue
   1.70%  haproxy             [.] pendconn_add

At this point the differences are mostly measurement noise.

This is tagged medium because the lock is changed, but no other part of
the code touches the queues, with nor without locking, so this should
remain invisible.
2021-06-22 18:43:56 +02:00
Willy Tarreau
a05704582c MINOR: server: replace the pendconns-related stuff with a struct queue
Just like for proxies, all three elements (pendconns, nbpend, queue_idx)
were moved to struct queue.
2021-06-22 18:43:14 +02:00
Willy Tarreau
7f3c1df248 MINOR: proxy: replace the pendconns-related stuff with a struct queue
All three elements (pendconns, nbpend, queue_idx) were moved to struct
queue.
2021-06-22 18:43:14 +02:00
Willy Tarreau
5941ef0a6c MINOR: lb/api: remove the locked argument from take_conn/drop_conn
This essentially reverts commit 2b4370078 ("MINOR: lb/api: let callers
of take_conn/drop_conn tell if they have the lock") that was merged
during 2.4 before the various locks could be eliminated at the lower
layers. Passing that information complicates the cleanup of the queuing
code and it's become useless.
2021-06-22 18:43:12 +02:00
Willy Tarreau
1b648c857b MEDIUM: queue: refine the locking in process_srv_queue()
The lock in process_srv_queue() was placed around the whole loop to
avoid the cost of taking/releasing it multiple times. But in practice
almost all calls to this function only dequeue a single connection, so
that argument doesn't really stand. However by placing the lock inside
the loop, we'd make it possible to release it before manipulating the
pendconn and waking the task up. That's what this patch does.

This increases the performance from 431k to 491k req/s on 16 threads
with 20 servers under leastconn.

The performance profile changes from this:
  14.09%  haproxy             [.] process_srv_queue
  10.22%  haproxy             [.] fwlc_srv_reposition
   6.39%  haproxy             [.] fwlc_get_next_server
   3.97%  haproxy             [.] pendconn_dequeue
   3.84%  haproxy             [.] pendconn_add

to this:
  13.03%  haproxy             [.] fwlc_srv_reposition
   8.08%  haproxy             [.] fwlc_get_next_server
   3.62%  haproxy             [.] process_srv_queue
   1.78%  haproxy             [.] pendconn_dequeue
   1.74%  haproxy             [.] pendconn_add

The difference is even slightly more visible in roundrobin which
does not have take_conn() call.
2021-06-22 18:41:55 +02:00
Willy Tarreau
3e92a31783 MINOR: queue: update proxy->served once out of the loop
It's not needed during all these operations and doesn't even affect
queueing in the LB algo, so we can safely update it out of the loop
and the lock.
2021-06-22 18:37:45 +02:00
Willy Tarreau
5304669e1b MEDIUM: queue: make pendconn_process_next_strm() only return the pendconn
It used to do far too much under the lock, including waking up tasks,
updating counters and repositionning entries in the load balancing algo.

This patch first moves all that stuff out of the function into the only
caller (process_srv_queue()). The decision to update the LB algo is now
taken out of the lock. The wakeups could be performed outside of the
loop by using a local list.

This increases the performance from 377k to 431k req/s on 16 threads
with 20 servers under leastconn.

The perf profile changes from this:
  23.17%  haproxy             [.] process_srv_queue
   6.58%  haproxy             [.] pendconn_add
   6.40%  haproxy             [.] pendconn_dequeue
   5.48%  haproxy             [.] fwlc_srv_reposition
   3.70%  haproxy             [.] fwlc_get_next_server

to this:
  13.95%  haproxy             [.] process_srv_queue
   9.96%  haproxy             [.] fwlc_srv_reposition
   6.21%  haproxy             [.] fwlc_get_next_server
   3.96%  haproxy             [.] pendconn_dequeue
   3.75%  haproxy             [.] pendconn_add
2021-06-22 18:37:41 +02:00
Amaury Denoyelle
0274286dd3 BUG/MAJOR: server: fix deadlock when changing maxconn via agent-check
The server_parse_maxconn_change_request locks the server lock. However,
this function can be called via agent-checks or lua code which already
lock it. This bug has been introduced by the following commit :

  commit 79a88ba3d0
  BUG/MAJOR: server: prevent deadlock when using 'set maxconn server'

This commit tried to fix another deadlock with can occur because
previoulsy server_parse_maxconn_change_request requires the server lock
to be held. However, it may call internally process_srv_queue which also
locks the server lock. The locking policy has thus been updated. The fix
is functional for the CLI 'set maxconn' but fails to address the
agent-check / lua counterparts.

This new issue is fixed in two steps :
- changes from the above commit have been reverted. This means that
  server_parse_maxconn_change_request must again be called with the
  server lock.

- to counter the deadlock fixed by the above commit, process_srv_queue
  now takes an argument to render the server locking optional if the
  caller already held it. This is only used by
  server_parse_maxconn_change_request.

The above commit was subject to backport up to 1.8. Thus this commit
must be backported in every release where it is already present.
2021-06-22 11:39:20 +02:00
Willy Tarreau
901972e261 MINOR: queue: update the stream's pend_pos before queuing it
Since commit c7eedf7a5 ("MINOR: queue: reduce the locked area in
pendconn_add()") the stream's pend_pos is set out of the lock, after
the pendconn is queued. While this entry is only manipulated by the
stream itself and there is no bug caused by this right now, it's a
bit dangerous because another thread could decide to look at this
field during dequeuing and could randomly see something else. Also
in case of crashes, memory inspection wouldn't be as trustable.
Let's assign the pendconn before it can be found in the queue.
2021-06-18 18:21:18 +02:00
Amaury Denoyelle
34897d2eff MINOR: ssl: support ssl keyword for dynamic servers
Activate the 'ssl' keyword for dynamic servers. This is the final step
to have ssl dynamic servers feature implemented. If activated,
ssl_sock_prepare_srv_ctx will be called at the end of the 'add server'
CLI handler.

At the same time, update the management doc to list all ssl keywords
implemented for dynamic servers.
2021-06-18 16:42:26 +02:00
Amaury Denoyelle
71f9a06e4b MINOR: ssl: enable a series of ssl keywords for dynamic servers
These keywords are deemed safe-enough to be enable on dynamic servers.
Their parsing functions are simple and can be called at runtime.

- allow-0rtt
- alpn
- ciphers
- ciphersuites
- force-sslv3/tlsv10/tlsv11/tlsv12/tlsv13
- no-sslv3/tlsv10/tlsv11/tlsv12/tlsv13
- no-ssl-reuse
- no-tls-tickets
- npn
- send-proxy-v2-ssl
- send-proxy-v2-ssl-cn
- sni
- ssl-min-ver
- ssl-max-ver
- tls-tickets
- verify
- verifyhost

'no-ssl-reuse' and 'no-tls-tickets' are enabled to override the default
behavior.

'tls-tickets' is enable to override a possible 'no-tls-tickets' set via
the global option 'ssl-default-server-options'.

'force' and 'no' variants of tls method options are useful to override a
possible 'ssl-default-server-options'.
2021-06-18 16:42:26 +02:00
Amaury Denoyelle
fde82605cd MINOR: ssl: support crl arg for dynamic servers
File-access through ssl_store_load_locations_file is deactivated if
srv_parse_crl is used at runtime for a dynamic server. The crl must
have already been loaded either in the config or through the 'ssl crl'
CLI commands.
2021-06-18 16:42:26 +02:00
Amaury Denoyelle
93be21e0c6 MINOR: ssl: support crt arg for dynamic servers
File-access through ssl_store_load_locations_file is deactivated if
srv_parse_crt is used at runtime for a dynamic server. The cert must
have already been loaded either in the config or through the 'ssl cert'
CLI commands.
2021-06-18 16:42:26 +02:00
Amaury Denoyelle
482550280a MINOR: ssl: support ca-file arg for dynamic servers
File-access through ssl_store_load_locations_file is deactivated if
srv_parse_ca_file is used at runtime for a dynamic server. The ca-file
must have already been loaded either in the config or through the 'ssl
ca-file' CLI commands.
2021-06-18 16:42:26 +02:00
Amaury Denoyelle
7addf56b72 MINOR: ssl: split parse functions for alpn/check-alpn
This will be in preparation for support of ssl on dynamic servers. The
'alpn' keyword will be allowed for dynamic servers but not the
'check-alpn'.

The alpn parsing is extracted into a new function parse_alpn. Each
srv_parse_alpn and srv_parse_check_alpn called it.
2021-06-18 16:42:26 +02:00
Amaury Denoyelle
36aa451a4e MINOR: ssl: render file-access optional on server crt loading
The function ssl_sock_load_srv_cert will be used at runtime for dynamic
servers. If the cert is not loaded on ckch tree, we try to access it
from the file-system.

Now this access operation is rendered optional by a new function
argument. It is only allowed at parsing time, but will be disabled for
dynamic servers at runtime.
2021-06-18 16:42:25 +02:00
Amaury Denoyelle
b89d3d3de7 MINOR: server: disable CLI 'set server ssl' for dynamic servers
'set server ssl' uses ssl parameters from default-server. As dynamic
servers does not reuse any default-server parameters, this command has
no sense for them.
2021-06-18 16:42:25 +02:00
Amaury Denoyelle
1f9333b30e MINOR: ssl: check allocation in parse npn/sni
These checks are especially required now as this function will be used
at runtime for dynamic servers.
2021-06-18 16:42:25 +02:00
Amaury Denoyelle
cbbf87f119 MINOR: ssl: check allocation in parse ciphers/ciphersuites/verifyhost
These checks are especially required now as this function will be used
at runtime for dynamic servers.
2021-06-18 16:42:25 +02:00
Amaury Denoyelle
949c94e462 MINOR: ssl: check allocation in ssl_sock_init_srv
These checks are especially required now as this function will be used
at runtime for dynamic servers.
2021-06-18 16:42:25 +02:00
Amaury Denoyelle
c593bcdb43 MINOR: ssl: always initialize random generator
Explicitly call ssl_initialize_random to initialize the random generator
in init() global function. If the initialization fails, the startup is
interrupted.

This commit is in preparation for support of ssl on dynamic servers. To
be able to activate ssl on dynamic servers, it is necessary to ensure
that the random generator is initialized on startup regardless of the
config. It cannot be called at runtime as access to /dev/urandom is
required.

This also has the effect to fix the previous non-consistent behavior.
Indeed, if bind or server in the config are using ssl, the
initialization function was called, and if it failed, the startup was
interrupted. Otherwise, the ssl initialization code could have been
called through the ssl server for lua, but this times without blocking
the startup on error. Or not called at all if lua was deactivated.
2021-06-18 16:42:25 +02:00
Amaury Denoyelle
b11ad9ed61 MINOR: ssl: fix typo in usage for 'new ssl ca-file'
Fix the usage for the command new ssl ca-file, which has a missing '-'
dash separator.
2021-06-18 16:42:25 +02:00
Tim Duesterhus
3bc6af417d BUG/MINOR: cache: Correctly handle existing-but-empty 'accept-encoding' header
RFC 7231#5.3.4 makes a difference between a completely missing
'accept-encoding' header and an 'accept-encoding' header without any values.

This case was already correctly handled by accident, because an empty accept
encoding does not match any known encoding. However this resulted in the
'other' encoding being added to the bitmap. Usually this also succeeds in
serving cached responses, because the cached response likely has no
'content-encoding', thus matching the identity case instead of not serving the
response, due to the 'other' encoding. But it's technically not 100% correct.

Fix this by special-casing 'accept-encoding' values with a length of zero and
extend the test to check that an empty accept-encoding is correctly handled.
Due to the reasons given above the test also passes without the change in
cache.c.

Vary support was added in HAProxy 2.4. This fix should be backported to 2.4+.
2021-06-18 15:48:20 +02:00
Christopher Faulet
0ba54bb401 BUG/MINOR: server/cli: Fix locking in function processing "set server" command
The commit c7b391aed ("BUG/MEDIUM: server/cli: Fix ABBA deadlock when fqdn
is set from the CLI") introduced 2 bugs. The first one is a typo on the
server's lock label (s/SERVER_UNLOCK/SERVER_LOCK/). The second one is about
the server's lock itself. It must be acquired to execute the "agent-send"
subcommand.

The patch above is marked to be backported as far as 1.8. Thus, this one
must also backported as far 1.8.

BUG/MINOR: server/cli: Don't forget to lock server on agent-send subcommand
2021-06-18 09:16:32 +02:00
Christopher Faulet
e886dd5c32 BUG/MINOR: resolvers: Use resolver's lock in resolv_srvrq_expire_task()
The commit dcac41806 ("BUG/MEDIUM: resolvers: Add a task on servers to check
SRV resolution status") introduced a type. In resolv_srvrq_expire_task()
function, the resolver's lock must be used instead of the resolver itself.

This patch must be backported with the patch above (at least as far as 2.2).
2021-06-18 09:15:35 +02:00
Amaury Denoyelle
655dec81bd BUG/MINOR: backend: do not set sni on connection reuse
When reusing a backend connection, do not reapply the SNI on the
connection. It should already be defined when the connection was
instantiated on a previous connect_server invocation. As the SNI is a
parameter used to select a connection, only connection with same value
can be reused.

The impact of this bug is unknown and may be null. No memory leak has
been reported by valgrind. So this is more a cleaning fix.

This commit relies on the SF_SRV_REUSED flag and thus depends on the
following fix :
  BUG/MINOR: backend: restore the SF_SRV_REUSED flag original purpose

This should be backported up to 2.4.
2021-06-17 18:01:57 +02:00
Amaury Denoyelle
2b1d91758d BUG/MINOR: backend: restore the SF_SRV_REUSED flag original purpose
The SF_SRV_REUSED flag was set if a stream reused a backend connection.
One of its purpose is to count the total reuse on the backend in
opposition to newly instantiated connection.

However, the flag was diverted from its original purpose since the
following commit :

  e8f5f5d8b2
  BUG/MEDIUM: servers: Only set SF_SRV_REUSED if the connection if fully ready.

With this change, the flag is not set anymore if the mux is not ready
when a connection is picked for reuse. This can happen for multiplexed
connections which are inserted in the available list as soon as created
in http-reuse always mode. The goal of this change is to not retry
immediately this request in case on an error on the same server if the
reused connection is not fully ready.

This change is justified for the retry timeout handling but it breaks
other places which still uses the flag for its original purpose. Mainly,
in this case the wrong 'connect' backend counter is incremented instead
of the 'reuse' one. The flag is also used in http_return_srv_error and
may have an impact if a http server error is replied for this stream.

To fix this problem, the original purpose of the flag is restored by
setting it unconditionaly when a connection is reused. Additionally, a
new flag SF_SRV_REUSED_ANTICIPATED is created. This flag is set when the
connection is reused but the mux is not ready yet. For the timeout
handling on error, the request is retried immediately only if the stream
reused a connection without this newly anticipated flag.

This must be backported up to 2.1.
2021-06-17 17:58:50 +02:00
Christopher Faulet
dcac418062 BUG/MEDIUM: resolvers: Add a task on servers to check SRV resolution status
When a server relies on a SRV resolution, a task is created to clean it up
(fqdn/port and address) when the SRV resolution is considered as outdated
(based on the resolvers 'timeout' value). It is only possible if the server
inherits outdated info from a state file and is no longer selected to be
attached to a SRV item. Note that most of time, a server is attached to a
SRV item. Thus when the item becomes obsolete, the server is cleaned
up.

It is important to have such task to be sure the server will be free again
to have a chance to be resolved again with fresh information. Of course,
this patch is a workaround to solve a design issue. But there is no other
obvious way to fix it without rewritting all the resolvers part. And it must
be backportable.

This patch relies on following commits:
 * MINOR: resolvers: Clean server in a dedicated function when removing a SRV item
 * MINOR: resolvers: Remove server from named_servers tree when removing a SRV item

All the series must be backported as far as 2.2 after some observation
period. Backports to 2.0 and 1.8 must be evaluated.
2021-06-17 16:52:35 +02:00
Christopher Faulet
73001ab6e3 MINOR: resolvers: Remove server from named_servers tree when removing a SRV item
When a server is cleaned up because the corresponding SRV item is removed,
we always remove the server from the srvrq's name_servers tree. For now, it
is useless because, if a server was attached to a SRV item, it means it was
already removed from the tree. But it will be mandatory to fix a bug.
2021-06-17 16:52:35 +02:00
Christopher Faulet
11c6c39656 MINOR: resolvers: Clean server in a dedicated function when removing a SRV item
A dedicated function is now used to clean up servers when a SRV item becomes
obsolete or when a requester is removed from a resolution. This patch is
mandatory to fix a bug.
2021-06-17 16:52:35 +02:00
Christopher Faulet
c7b391aed2 BUG/MEDIUM: server/cli: Fix ABBA deadlock when fqdn is set from the CLI
To perform servers resolution, the resolver's lock is first acquired then
the server's lock when necessary. However, when the fqdn is set via the CLI,
the opposite is performed. So, it is possible to experience an ABBA
deadlock.

To fix this bug, the server's lock is acquired and released for each
subcommand of "set server" with an exception when the fqdn is set. The
resolver's lock is first acquired. Of course, this means we must be sure to
have a resolver to lock.

This patch must be backported as far as 1.8.
2021-06-17 16:52:14 +02:00
Christopher Faulet
a386e78823 BUG/MINOR: server: Forbid to set fqdn on the CLI if SRV resolution is enabled
If a server is configured to rely on a SRV resolution, we must forbid to
change its fqdn on the CLI. Indeed, in this case, the server retrieves its
fqdn from the SRV resolution. If the fqdn is changed via the CLI, this
conflicts with the SRV resolution and leaves the server in an undefined
state. Most of time, the SRV resolution remains enabled with no effect on
the server (no update). Some time the A/AAAA resolution for the new fqdn is
not enabled at all. It depends on the server state and resolver state when
the CLI command is executed.

This patch must be backported as far as 2.0 (maybe to 1.8 too ?) after some
observation period.
2021-06-17 16:17:14 +02:00
Miroslav Zagorac
8a8f270f6a CLEANUP: server: a separate function for initializing the per_thr field
To avoid repeating the same source code, allocating memory and initializing
the per_thr field from the server structure is transferred to a separate
function.
2021-06-17 16:07:10 +02:00
Ilya Shipitsin
213bb99f9e CLEANUP: assorted typo fixes in the code and comments
This is 24th iteration of typo fixes
2021-06-17 09:02:16 +02:00
Willy Tarreau
3a53707160 BUG/MINOR: mux-h2/traces: bring back the lost "sent H2 REQ/RES" traces
In 2.4, commit d1ac2b90c ("MAJOR: htx: Remove the EOM block type and
use HTX_FL_EOM instead") changed the HTX processing to destroy the
blocks as they are processed. So the traces that were emitted at the
end of the send headers functions didn't have anything to show.

Let's move these traces earlier in the function, right before the HTX
processing, so that everything is still in place.

This should be backported to 2.4.
2021-06-17 08:43:43 +02:00
Willy Tarreau
29268e9a3c BUG/MINOR: mux-h2/traces: bring back the lost "rcvd H2 REQ" trace
Since commit 7d013e796 ("BUG/MEDIUM: mux-h2: Xfer rxbuf to the upper
layer when creating a front stream"), the rxbuf is lost during the
call to h2c_frt_stream_new(), so the trace that happens later cannot
find a request there and we've lost the useful part indicating what
the request looked like. Let's move the trace before this call.

This should be backported to 2.4.
2021-06-17 08:43:27 +02:00
Willy Tarreau
ee4684f65b MINOR: mux-h2: obey http-ignore-probes during the preface
We're seeing some browsers setting up multiple connections and closing
some to just keep one. It looks like they do this in case they'd
negotiate H1. This results in aborted prefaces and log pollution about
bad requests and "PR--" in the status flags.

We already have an option to ignore connections with no data, it's called
http-ignore-probes. But it was not used by the H2 mux. However it totally
makes sense to use it during the preface.

This patch changes this so that connections aborted before sending the
preface can avoid being logged.

This should be backported to 2.4 and 2.3 at least, and probably even
as far as 2.0.
2021-06-17 08:08:48 +02:00
Willy Tarreau
fc8e438637 BUG/MINOR: stats: make "show stat typed desc" work again
As part of the changes to support per-module stats data in 2.3-dev6
with commit ee63d4bd6 ("MEDIUM: stats: integrate static proxies stats
in new stats"), a small change resulted in the description field to
be replaced by the name field, making it pointless. Let's fix this
back.

This should fix issue #1291. Thanks to Nick Ramirez for reporting this
issue.

This patch can be backported to 2.3.
2021-06-17 07:25:22 +02:00
Willy Tarreau
9abb317683 CLEANUP: mux-h2/traces: better align user messages
"sent H2 request" was already misaligned with the 3 other ones
(sent/rcvd, request/response), and now with "new H2 connection" that's
yet another alignment making the traces even less legible. Let's just
realign all 5 messages, this even eases quick pointer comparisons. This
should probably be backported to 2.4 as it's where it's the most likely
to be used in the mid-term.
2021-06-16 18:32:42 +02:00
Willy Tarreau
8e6f749f18 MINOR: mux-h2/trace: report a few connection-level info during h2_init()
It is currently very difficult to match some H2 trace outputs against
some log extracts because there's no exactly equivalent info.

This patch tries to address this by adding a TRACE_USER() call in h2_init()
that is matched in h2_trace() to report:
  - connection pointer and direction
  - frontend's name or server's name
  - transport layer and control layer (e.g. "SSL/tcpv4")
  - source and/or destination depending on what is set

This now permits to get something like this at verbosity level complete:

  <0>2021-06-16T18:30:19.810897+02:00 [00|h2|1|mux_h2.c:1006] new H2 connection : h2c=0x19fee50(F,PRF) : conn=0x7f373c026850(IN) fe=h2gw RAW/tcpv4 src=127.0.0.1:19540
  <0>2021-06-16T18:30:19.810919+02:00 [00|h2|1|mux_h2.c:2731] rcvd H2 request  : h2c=0x19fee50(F,FRH)
  <0>2021-06-16T18:30:19.810998+02:00 [00|h2|1|mux_h2.c:1006] new H2 connection : h2c=0x1a04ee0(B,PRF) : conn=0x1a04ce0(OUT) sv=h2gw/s1 RAW/tcpv4 dst=127.0.0.1:4446
2021-06-16 18:30:42 +02:00
Willy Tarreau
d943a044aa MINOR: connection: add helper conn_append_debug_info()
This function appends to a buffer some information from a connection.
This will be used by traces and possibly some debugging as well. A
frontend/backend/server, transport/control layers, source/destination
ip:port, connection pointer and direction are reported depending on
the available information.
2021-06-16 18:30:42 +02:00
Willy Tarreau
b74debd826 BUG/MINOR: mux-h1: do not skip the error response on bad requests
Since 2.4-dev3 with commit c4bfa59f1 ("MAJOR: mux-h1: Create the client
stream as later as possible"), a request error doesn't result in any
error response if "option http-ignore-probes" is set, there's just a
close. This is caused by an unneeded b_reset() in h1_process_demux()'s
error path, which makes h1_handle_bad_req() believe there was an empty
request. There is no reason for this reset to be there, it must have
been a leftover of an earlier attempt at dealing with the error, let's
drop it.

This should be backported to 2.4.
2021-06-16 15:06:43 +02:00
Willy Tarreau
f9a7c442f6 MINOR: backend: only skip LB when there are actual connections
In 2.3, a significant improvement was brought against situations where
the queue was heavily used, because some LB algos were still checked
for no reason before deciding to put the request into the queue. This
was commit 82cd5c13a ("OPTIM: backend: skip LB when we know the backend
is full").

As seen in previous commit ("BUG/MAJOR: queue: set SF_ASSIGNED when
setting strm->target on dequeue") the dequeuing code is extremely
tricky, and the optimization above tends to emphasize transient issues
by making them permanent until the next reload, which is not acceptable
as the code must always be robust against any bad situation.

This commit brings a protection against such a situation by slightly
relaxing the test. Instead of checking that there are pending connections
in the backend queue, it also verifies that the backend's connections are
not solely composed of queued connections, which would then indicate we
are in this situation. This is not rocket science, but at least if the
situation happens, we know that it will unlock by itself once the streams
have left, as new requests will be allowed to reach the servers and to
flush the queue again.

This needs to be backported to 2.4 and 2.3.
2021-06-16 09:05:35 +02:00
Willy Tarreau
7867cebf31 BUG/MAJOR: queue: set SF_ASSIGNED when setting strm->target on dequeue
Commit 82cd5c13a ("OPTIM: backend: skip LB when we know the backend is
full") has uncovered a long-burried bug in the dequeing code: when a
server releases a connection, it picks a new one from the proxy's or
its queue. Technically speaking it only picks a pendconn which is a
link between a position in the queue and a stream. It then sets this
pendconn's target to itself, and wakes up the stream's task so that
it can try to connect again.

The stream then goes through the regular connection setup phases,
calls back_try_conn_req() which calls pendconn_dequeue(), which
sets the stream's target to the pendconn's and releases the pendconn.
It then reaches assign_server() which sees no SF_ASSIGNED and calls
assign_server_and_queue() to perform load balancing or queuing. This
one first destroys the stream's target and gets ready to perform load
balancing. At this point we're load-balancing for no reason since we
already knew what server was available. And this is where the commit
above comes into play: the check for the backend's queue above may
detect other connections that arrived in between, and will immediately
return FULL, forcing this request back into the queue. If the server
had a very low maxconn (e.g. 1 due to a long slowstart), it's possible
that this evicted connection was the last one on the server and that
no other one will ever be present to process the queue. Usually a
regularly processed request will still have its own srv_conn that will
be used during stream_free() to dequeue other connections. But if the
server had a down-up cycle, then a call to pendconn_grab_from_px()
may start to dequeue entries which had no srv_conn and which will have
no server slot to offer when they expire, thus maintaining the situation
above forever. Worse, as new requests arrive, there are always some
requests in the queue and the situation feeds on itself.

The correct fix here is to properly set SF_ASSIGNED in pendconn_dequeue()
when the stream's target is assigned (as it's what this flag means), so
as to avoid a load-balancing pass when dequeuing.

Many thanks to Pierre Cheynier for the numerous detailed traces he
provided that helped narrow this problem down.

This could be backported to all stable versions, but in practice only
2.3 and above are really affected since the presence of the commit
above. Given how tricky this code is it's better to limit it to those
versions that really need it.
2021-06-16 09:05:35 +02:00
Willy Tarreau
6fd0450b47 CLEANUP: shctx: remove the different inter-process locking techniques
With a single process, we don't need to USE_PRIVATE_CACHE, USE_FUTEX
nor USE_PTHREAD_PSHARED anymore. Let's only keep the basic spinlock
to lock between threads.
2021-06-15 16:52:42 +02:00
Willy Tarreau
b54ca70e7c MEDIUM: config: warn about "bind-process" deprecation
Let's indicate that "bind-process" is deprecated and scheduled for
removal in 2.7, as it only supports "1".
2021-06-15 16:52:42 +02:00
Willy Tarreau
e8422bf56b MEDIUM: global: remove the relative_pid from global and mworker
The relative_pid is always 1. In mworker mode we also have a
child->relative_pid which is always equalt relative_pid, except for a
master (0) or external process (-1), but these types are usually tested
for, except for one place that was amended to carefully check for the
PROC_O_TYPE_WORKER option.

Changes were pretty limited as most usages of relative_pid were for
designating a process in stats output and peers protocol.
2021-06-15 16:52:42 +02:00
Willy Tarreau
06987f4238 CLEANUP: global: remove unused definition of MAX_PROCS
This one was forced to 1 and the only reference was a test to verify it
was comprised between 1 and LONGBITS.
2021-06-15 16:52:42 +02:00
Willy Tarreau
44ea631b77 MEDIUM: cpu-set: make the proc a single bit field and not an array
We only have a single process now so we don't need to store the per-proc
CPU binding anymore.
2021-06-15 16:52:42 +02:00
Willy Tarreau
bda7c1decd MEDIUM: config: simplify cpu-map handling
As there's no more nbproc>1, we can remove some loops and tests in cpu-map.
Both the lack of thread number and thread 1 can count as the whole process
now (which is still used for whole process binding when threads are disabled).
2021-06-15 16:52:42 +02:00
Willy Tarreau
72faef3866 MEDIUM: global: remove dead code from nbproc/bind_proc removal
Lots of places iterating over nbproc or comparing with nbproc could be
simplified. Further, "bind-process" and "process" parsing that was
already limited to process 1 or "all" or "odd" resulted in a bind_proc
field that was either 0 or 1 during the init phase and later always 1.

All the checks for compatibilities were removed since it's not possible
anymore to run a frontend and a backend on different processes or to
have peers and stick-tables bound on different ones. This is the largest
part of this patch.

The bind_proc field was removed from both the proxy and the receiver
structs.

Since the "process" and "bind-process" directives are still parsed,
configs making use of correct values allowing process 1 will continue
to work.
2021-06-15 16:52:42 +02:00
Willy Tarreau
5301f5d72a CLEANUP: global: remove pid_bit and all_proc_mask
They were already set to 1 and never changed. Let's remove them and
replace their references with 1.
2021-06-15 16:52:42 +02:00
Willy Tarreau
91358595f8 CLEANUP: global: remove the nbproc field from the global structure
Let's use 1 in the rare places where it was still referenced since it's
now its only possible value.
2021-06-15 16:52:42 +02:00
Willy Tarreau
6185a0343b MINOR: mworker: remove the initialization loop over processes
There was a loop used to prepare structures for all current processes.
Let's just assume there's a single iteration now.
2021-06-15 16:52:42 +02:00
Willy Tarreau
d67ff340a5 MEDIUM: init: remove the loop over processes during init
There was a loop iterating over all nbproc values during init that
couldn't be immediately removed because the loop's index was used
to distinguish a child from a parent. That's now fixed by replacing
the iterator with an in_parent flag. All bindings that were checking
(1UL << proc) or cpu_map.proc[proc] were adjusted to always use zero
for proc.
2021-06-15 16:52:42 +02:00
Willy Tarreau
e34cf28011 BUG/MINOR: mworker: fix typo in chroot error message
Since its introduction in 1.8 with commit 095ba4c24 ("MEDIUM: mworker:
replace systemd mode by master worker mode"), it says "cannot chroot1(...)"
which seems to be a leftover of a debug message. It could be backported but
probably nobody will notice.
2021-06-15 16:52:07 +02:00
Willy Tarreau
4c19e99621 BUG/MINOR: ssl: use atomic ops to update global shctx stats
The global shctx lookups and misses was updated without using atomic
ops, so the stats available in "show info" are very likely off by a few
units over time. This should be backported as far as 1.8. Versions
without _HA_ATOMIC_INC() can use HA_ATOMIC_ADD(,1).
2021-06-15 16:52:07 +02:00
Willy Tarreau
9e467af804 BUG/MEDIUM: shctx: use at least thread-based locking on USE_PRIVATE_CACHE
Since threads were introduced in 1.8, the USE_PRIVATE_CACHE mode of the
shctx was not updated to use locks. Originally it was meant to disable
sharing between processes, so it removes the lock/unlock instructions.
But with threads enabled, it's not possible to work like this anymore.

It's easy to see that once built with private cache and threads enabled,
sending violent SSL traffic to the the process instantly makes it die.
The HTTP cache is very likely affected as well.

This patch addresses this by falling back to our native spinlocks when
USE_PRIVATE_CACHE is used. In practice we could use them also for other
modes and remove all older implementations, but this patch aims at keeping
the changes very low and easy to backport. A new SHCTX_LOCK label was
added to help with debugging, but OTHER_LOCK might be usable as well
for backports.

An even lighter approach for backports may consist in always declaring
the lock (or reusing "waiters"), and calling pl_take_s() for the lock()
and pl_drop_s() for the unlock() operation. This could even be used in
all modes (process and threads), even when thread support is disabled.

Subsequent patches will further clean up this area.

This patch must be backported to all supported versions since 1.8.
2021-06-15 16:52:07 +02:00
Amaury Denoyelle
8ff0434b61 BUG/MEDIUM: server: do not auto insert a dynamic server in px addr_node
Until then, the servers were automatically attached on their creation
into the proxy addr_node tree via _srv_parse_init. In case of an invalid
dynamic server which is instantly freed, no detach operation was made
leaving a NULL server in the tree.

Change this mode of operation by marking the attach operation as
optional in _srv_parse_init. This operation is not conduct for a dynamic
server. The server is attached only at the end of the CLI handler when
it is marked as valid.

This must be backported up to 2.4.
2021-06-15 11:42:53 +02:00
Amaury Denoyelle
1613b4a75d BUG/MINOR: server: do not keep an invalid dynamic server in px ids tree
A bug is present when trying to create a dynamic server with a fixed id.
If the server is detected invalid due to a later parsing arguments
error, the server is not removed from the proxy used ids tree before
being freed.

Change the mode of operation of 'id' keyword parsing handler. The
insertion in the backend tree is removed from the handler and is not
taken in charge by parse_server for configuration parsing. For the
dynamic servers, the insertion is called at the end of the 'add server'
CLI handler when the server has been validated.

This must be backported up to 2.4.
2021-06-15 11:42:53 +02:00
Amaury Denoyelle
406aaef55a BUG/MEDIUM: server: do not forget to generate the dynamic servers ids
If no id is specified by the user for a dynamic server, it is necessary
to generate a new one. This operation is now done at the end of 'add
server' CLI handler. The server is then inserted into the proxy ids
tree.

Without this, several features may be broken for dynamic servers. Among
them, there is the "first" lb algorithm, the persistence using
stick-tables or the uniqueness internal check of srv_parse_id.

This must be backported up to 2.4.
2021-06-15 11:42:53 +02:00
Amaury Denoyelle
82d7f77463 BUG/MEDIUM: server: clear dynamic srv on delete from proxy id/name trees
Do not leave deleted server in used_server_id/used_server_addr backend
trees. This might lead to crashes if a deleted server is used through
these trees.

At this moment, dynamic servers are only added in used_server_id if they
have a fixed id. They are never inserted in used_server_addr as this
code is missing. So these new delete instructions are noop. However, a
fix will be provided soon to insert properly all dynamic servers in both
used_server_id and used_server_addr trees so the deletion counterpart
will be mandatory in the CLI server delete handler.

This must be backported to 2.4.
2021-06-15 11:38:06 +02:00
Amaury Denoyelle
31ddd76fef BUG/MEDIUM: server: extend thread-isolate over much of CLI 'add server'
Some config parsing handlers were designed to be run at startup on a
single-thread. When executing at runtime for dynamic servers,
thread-safety is not guaranteed. This is the case for example in
srv_parse_id which manipulates backend used_ids tree.

One solution could be to add locks but it might be tricky to found all
affected functions and it can be an easy source of deadlock. The other
solution which has been chosen is to use thread-isolation over almost
all of the cli_parse_add_server CLI handler.

For now this solution is sufficient. If some users make heavy use of the
'add server', hurting the overall performance, it will be necessary to
design a much thinner solution.

This must be backported up to 2.4.
2021-06-15 11:19:43 +02:00
Amaury Denoyelle
077c6b8d29 BUG/MINOR: stick-table: insert srv in used_name tree even with fixed id
If the server id is fixed in the configuration, it is immediately
inserted in the 'used_server_id' backend tree via srv_parse_id. On
check_config_validity, the dynamic id generation is thus skipped for
fixed-id servers. However, it must nevertheless be inserted in the
'used_server_name' backend tree.

This bug seems to be not noticeable for the user. Indeed, before the
fix, the search in sticking_rule_find_target always returned NULL for
the name, then the fallback search with server id succeeded, so the
persistence is properly applied. However with the fix the fallback
search is not executed anymore, which saves from the locking of
STK_SESS.

This should be backported up to 2.0.
2021-06-15 10:50:02 +02:00
Remi Tricot-Le Breton
6916493c29 MINOR: ssl: Use OpenSSL's ASN1_TIME convertor when available
The ASN1_TIME_to_tm function was added in OpenSSL1.1.1 so with this
version of the library we do not need our homemade time convertor
anymore.
2021-06-14 15:12:53 +02:00
Emeric Brun
caef19e0c7 BUG/MAJOR: resolvers: segfault using server template without SRV RECORDs
This patch fix the issue adding a test in srvrq before registering
the server on it during server template init.

This was a regression due to commit :
3406766d57

This should be backported with this previous commit (until 2.0)
2021-06-14 11:04:02 +02:00
Willy Tarreau
2a651e2d0d BUILD: log: remove unused fmt_directive()
fmt_directive() became unused after the removal of the deprecated
tags, and it emits a warning on some compilers. Let's drop it.
2021-06-11 17:32:03 +02:00
Willy Tarreau
3ae1d1eab9 BUILD: init: remove initialization of multi-process thread mappings
This broke the build with recent compilers and is not used anyway.
2021-06-11 17:28:19 +02:00
Willy Tarreau
b63dbb7b2e MAJOR: config: remove parsing of the global "nbproc" directive
This one was deprecated in 2.3 and marked for removal in 2.5. It suffers
too many limitations compared to threads, and prevents some improvements
from being engaged. Instead of a bypassable startup error, there is now
a hard error.

The parsing code was removed, and very few obvious cases were as well.
The code is deeply rooted at certain places (e.g. "for" loops iterating
from 0 to nbproc) so it will not be that trivial to remove everywhere.
The "bind" and "bind-process" parsers will have to be adjusted, though
maybe not completely changed if we later want to support thread groups
for large NUMA machines. Some stats socket restrictions were removed,
and the doc was updated according to what was done. A few places in the
doc still refer to nbproc and will have to be revisited. The master-worker
code also refers to the process number to distinguish between master and
workers and will have to be carefully adjusted. The MAX_PROCS macro was
reset to 1, this will at least reduce the size of some remaining arrays.

Two regtests were dependieng on this directive, one with an explicit
"nbproc 1" and another one testing the master's CLI using nbproc 4.
Both were adapted.
2021-06-11 17:02:13 +02:00
Willy Tarreau
eb778248d9 MEDIUM: proxy: remove the deprecated "grace" keyword
Commit ab0a5192a ("MEDIUM: config: mark "grace" as deprecated") marked
the "grace" keyword as deprecated in 2.3, tentative removal for 2.4
with a hard deadline in 2.5, so let's remove it and return an error now.
This old and outdated feature was incompatible with soft-stop, reload
and socket transfers, and keeping it forced ugly hacks in the lower
layers of the protocol stack.
2021-06-11 16:57:34 +02:00
Willy Tarreau
d2f2537d1b MINOR: config: remove deprecated option "http-tunnel"
It was marked as deprecated in 2.1-dev2 and for removal in 2.2, but it
was missed. A warning was already emitted and the doc didn't refer to
it any more, let's now get rid of it.
2021-06-11 16:57:34 +02:00
Willy Tarreau
6ba69841f8 MINOR: config: reject long-deprecated "option forceclose"
It's been warning as being deprecated since 2.0-dev4, it's about time
to drop it now. The error message recommends to either remove it or
use "option httpclose" instead. It's still referred to in the old
internal doc about the connection header, which itself seems highly
inaccurate by now.
2021-06-11 16:57:34 +02:00
Willy Tarreau
4a83977283 MINOR: http: remove the long deprecated "set-cookie()" sample fetch function
This one was marked as deprecated 9 years ago by commit 28376d62c
("MEDIUM: http: merge ACL and pattern cookie fetches into a single one")
and has disappeared from any documentation, so it never appeared in any
released version. Let's remove it now.
2021-06-11 16:57:34 +02:00
Willy Tarreau
fd6ab66041 MINOR: log: remove the long-deprecated early log-format tags
The following 10 log-format tags were implemented during log-format
development and changed before the release. They were marked as deprecated
in 2012 by commit 2beef5888 ("MEDIUM: log: change a few log tokens to make
them easier to remember") and were not documented. They've been emitting a
warning since then, with a suggestion of the one to use instead. Let's get
rid of them now.

      Bi => bi, Bp => bp, Ci => ci, Cp => cp, Fi => fi
      Fp => fp, Si => si, Sp => sp, cc => CC, cs => CS
2021-06-11 16:57:34 +02:00
Willy Tarreau
9862787e8f MINOR: config: completely remove support for "no option http-use-htx"
This one used to still be supported, emitting a warning about it being
deprecated and the default since 2.1. Let's remove it now.
2021-06-11 16:57:34 +02:00
Willy Tarreau
eb9d90a5a2 MINOR: config: remove support for deprecated option "tune.chksize"
It was marked as deprecated for immediate removal as it was not used,
let's reject it and remove it from the doc. A specific error suggests
to check tune.bufsize instead.
2021-06-11 16:57:34 +02:00
Christopher Faulet
85af93b8c7 BUG/MINOR: server-state: load SRV resolution only if params match the config
When the state of a server is loaded, if there is no hostname defined for
this server and if a fqdn and a server record are retrieved from the state
file, it means the server should rely on a SRV resolution. But we must be
sure the server is configured this way. A SRV resolution must be configured
with the same SRV record. This part must be skipped if there is no SRV
resolution configured for this server or if the SRV record used is not the
same.

This patch should be backported as far as 1.8 after some observation period.
2021-06-11 16:16:20 +02:00
Emeric Brun
3406766d57 MEDIUM: resolvers: add a ref between servers and srv request or used SRV record
This patch add a ref into servers to register them onto the
record answer item used to set their hostnames.

It also adds a head list into 'srvrq' to register servers free
to be affected to a SRV record.

A head of a tree is also added to srvrq to put servers which
present a hotname in server state file. To re-link them fastly
to the matching record as soon an item present the same name.

This results in better performances on SRV record response
parsing.

This is an optimization but it could avoid to trigger the haproxy's
internal wathdog in some circumstances. And for this reason
it should be backported as far we can (2.0 ?)
2021-06-11 16:16:16 +02:00
Emeric Brun
bd78c912fd MEDIUM: resolvers: add a ref on server to the used A/AAAA answer item
This patch adds a head list into answer items on servers which use
this record to set their IPs. It makes lookup on duplicated ip faster and
allow to check immediatly if an item is still valid renewing the IP.

This results in better performances on A/AAAA resolutions.

This is an optimization but it could avoid to trigger the haproxy's
internal wathdog in some circumstances. And for this reason
it should be backported as far we can (2.0 ?)
2021-06-11 16:16:16 +02:00
Emeric Brun
12ca658dbe BUG/MINOR: resolvers: answser item list was randomly purged or errors
In case of SRV records, The answer item list was purged by the
error callback of the first requester which considers the error
could not be safely ignored. It makes this item list unavailable
for subsequent requesters even if they consider the error
could be ignored.

On A resolution or do_resolve action error, the answer items were
never trashed.

This patch re-work the error callbacks and the code to check the return code
If a callback return 1, we consider the error was ignored and
the answer item list must be kept. At the opposite, If all error callbacks
of all requesters of the same resolution returns 0 the list will be purged

This patch should be backported as far as 2.0.
2021-06-11 16:16:16 +02:00
Christopher Faulet
0fe1864f7d CLEANUP: l7-retries: do not test the buffer before calling b_alloc()
The return value is enough now to know if the allocation succeeded or
failed.

This cleanup was already pushed by Willy (f499f50) but a revert crushed
it. It may be backported to the 2.4 because the original patch was done on
this version.
2021-06-11 16:04:28 +02:00
Christopher Faulet
bf76df12a6 BUG/MINOR: h1-htx: Fix a signess bug with char data type when parsing chunk size
On some platform, a char may be unsigned. Of course, we should not rely on
the signess of a char to be portable. Unfortunatly, since the commit
a835f3cb ("MINOR: h1-htx: Use a correlation table to speed-up small chunks
parsing") we rely on it to test the value retrieved from the hexadecimal
correlation table when the size of a chunk is parsed.

To fix the bug, we now test the result is in the range [0,15] with a bitwise
AND.

This patch should fix the issue #1272. It is 2.5-specific, no backport is
needed except if the commit above is backported.
2021-06-11 14:15:48 +02:00
Christopher Faulet
5cd0e528cf BUG/MINOR: mux-fcgi: Expose SERVER_SOFTWARE parameter by default
As specified in the RFC3875 (section 4.1.17), this parameter must be set to
the name and version of the information server software making the CGI
request. Thus, it is now added to the default parameters defined by
HAProxy. It is set to the string "HAProxy $version".

This patch should fix the issue #1285 and must be backported as far as 2.2.
2021-06-11 14:15:48 +02:00
Christopher Faulet
1cf414b522 BUG/MAJOR: htx: Fix htx_defrag() when an HTX block is expanded
When an HTX block is expanded, a defragmentation may be performed first to
have enough space to copy the new data. When it happens, the meta data of
the HTX message must take account of the new data length but copied data are
still unchanged at this stage (because we need more space to update the
message content). And here there is a bug because the meta data are updated
by the caller. It means that when the blocks content is copied, the new
length is already set. Thus a block larger than the reality is copied and
data outside the buffer may be accessed, leading to a crash.

To fix this bug, htx_defrag() is updated to use an extra argument with the
new meta data to use for the referenced block. Thus the caller does not need
to update the HTX message by itself. However, it still have to update the
data.

Most of time, the bug will be encountered in the HTTP compression
filter. But, even if it is highly unlikely, in theory it is also possible to
hit it when a HTTP header (or only its value) is replaced or when the
start-line is changed.

This patch must be backported as far as 2.0.
2021-06-11 14:05:34 +02:00
Remi Tricot-Le Breton
3faf0cbba6 BUILD: ssl: Fix compilation with BoringSSL
The ifdefs surrounding the "show ssl ocsp-response" functionality that
were supposed to disable the code with BoringSSL were built the wrong
way.

It does not need to be backported.
2021-06-10 19:01:13 +02:00
Willy Tarreau
8715dec6f9 MEDIUM: pools: remove the locked pools implementation
Now that the modified lockless variant does not need a DWCAS anymore,
there's no reason to keep the much slower locked version, so let's
just get rid of it.
2021-06-10 17:46:50 +02:00
Willy Tarreau
2a4523f6f4 BUG/MAJOR: pools: fix possible race with free() in the lockless variant
In GH issue #1275, Fabiano Nunes Parente provided a nicely detailed
report showing reproducible crashes under musl. Musl is one of the libs
coming with a simple allocator for which we prefer to keep the shared
cache. On x86 we have a DWCAS so the lockless implementation is enabled
for such libraries.

And this implementation has had a small race since day one: the allocator
will need to read the first object's <next> pointer to place it into the
free list's head. If another thread picks the same element and immediately
releases it, while both the local and the shared pools are too crowded, it
will be freed to the OS. If the libc's allocator immediately releases it,
the memory area is unmapped and we can have a crash while trying to read
that pointer. However there is no problem as long as the item remains
mapped in memory because whatever value found there will not be placed
into the head since the counter will have changed.

The probability for this to happen is extremely low, but as analyzed by
Fabiano, it increases with the buffer size. On 16 threads it's relatively
easy to reproduce with 2MB buffers above 200k req/s, where it should
happen within the first 20 seconds of traffic usually.

This is a structural issue for which there are two non-trivial solutions:
  - place a read lock in the alloc call and a barrier made of lock/unlock
    in the free() call to force to serialize operations; this will have
    a big performance impact since free() is already one of the contention
    points;

  - change the allocator to use a self-locked head, similar to what is
    done in the MT_LISTS. This requires two memory writes to the head
    instead of a single one, thus the overhead is exactly one memory
    write during alloc and one during free;

This patch implements the second option. A new POOL_DUMMY pointer was
defined for the locked pointer value, allowing to both read and lock it
with a single xchg call. The code was carefully optimized so that the
locked period remains the shortest possible and that bus writes are
avoided as much as possible whenever the lock is held.

Tests show that while a bit slower than the original lockless
implementation on large buffers (2MB), it's 2.6 times faster than both
the no-cache and the locked implementation on such large buffers, and
remains as fast or faster than the all implementations when buffers are
48k or higher. Tests were also run on arm64 with similar results.

Note that this code is not used on modern libcs featuring a fast allocator.

A nice benefit of this change is that since it removes a dependency on
the DWCAS, it will be possible to remove the locked implementation and
replace it with this one, that is then usable on all systems, thus
significantly increasing their performance with large buffers.

Given that lockless pools were introduced in 1.9 (not supported anymore),
this patch will have to be backported as far as 2.0. The code changed
several times in this area and is subject to many ifdefs which will
complicate the backport. What is important is to remove all the DWCAS
code from the shared cache alloc/free lockless code and replace it with
this one. The pool_flush() code is basically the same code as the
allocator, retrieving the whole list at once. If in doubt regarding what
barriers to use in older versions, it's safe to use the generic ones.

This patch depends on the following previous commits:

 - MINOR: pools: do not maintain the lock during pool_flush()
 - MINOR: pools: call malloc_trim() under thread isolation
 - MEDIUM: pools: use a single pool_gc() function for locked and lockless

The last one also removes one occurrence of an unneeded DWCAS in the
code that was incompatible with this fix. The removal of the now unused
seq field will happen in a future patch.

Many thanks to Fabiano for his detailed report, and to Olivier for
his help on this issue.
2021-06-10 17:46:50 +02:00
Willy Tarreau
9b3ed51371 MEDIUM: pools: use a single pool_gc() function for locked and lockless
Locked and lockless shared pools don't need to use a different pool_gc()
function because this function isolates itself during the operation, so
we do not need to rely on DWCAS nor any atomic operation in fact. Let's
just get rid of the lockless one in favor of the simple one. This should
even result in a faster execution.

The ifdefs were slightly moved so that we can have pool_gc() defined
as soon as there are global pools, this avoids duplicating the function.
2021-06-10 17:46:50 +02:00
Willy Tarreau
26ed183556 MINOR: pools: call malloc_trim() under thread isolation
pool_gc() was adjusted to run under thread isolation by commit c0e2ff202
("MEDIUM: memory: make pool_gc() run under thread isolation") so that the
underlying malloc() and free() don't compete between threads during these
potentially aggressive moments (especially when mmap/munmap are involved).

Commit 88366c292 ("MEDIUM: pools: call malloc_trim() from pool_gc()")
later added a call to malloc_trim() but made it outside of the thread
isolation, which is contrary to the principle explained above. Also it
missed it in the locked version, meaning that those without a lockless
implementation cannot benefit from trimming.

This patch fixes that by calling it before thread_release() in both
places.
2021-06-10 17:46:50 +02:00
Willy Tarreau
c88914379d MINOR: pools: do not maintain the lock during pool_flush()
The locked version of pool_flush() is absurd, it locks the pool for each
and every element to be released till the end. Not only this is extremely
inefficient, but it may even never finish if other threads spend their
time refilling the pool. The only case where this can happen is during
soft-stop so the risk remains limited, but it should be addressed.
2021-06-10 17:46:50 +02:00
Willy Tarreau
9a7aa3b4a1 BUG/MINOR: pools: make DEBUG_UAF always write to the to-be-freed location
Since the code was reorganized, DEBUG_UAF was still tested in the locked
pool code despite pools being disabled when DEBUG_UAF is used. Let's move
the test to pool_put_to_os() which is the one that is always called in
this condition.

The impact is only a possible misleading analysis during a troubleshooting
session due to a missing double-frees or free of const area test that is
normally already dealt with by the underlying code anyway. In practice it's
unlikely anyone will ever notice.

This should only be backported to 2.4.
2021-06-10 17:46:50 +02:00
Willy Tarreau
c239cde26f BUG/MINOR: pools: fix a possible memory leak in the lockless pool_flush()
The lockless version of pool_flush() had a leftover of the original
version causing the pool's first entry to be set to NULL at the end.
The problem is that it does this outside of any lock and in a non-
atomic way, so that any concurrent alloc+free would result in a lost
object.

The risk is low and the consequence even lower, given that pool_flush()
is only used in pool_destroy() (hence single-threaded) or by stream_free()
during a soft-stop (not the place where most allocations happen), so in
the worst case it could result in valgrind complaining on soft-stop.

The bug was introduced with the first version of the code, in 1.9, so
the fix can be backported to all stable versions.
2021-06-10 17:46:50 +02:00
Amaury Denoyelle
efbf35caf9 BUG/MINOR: server: explicitly set "none" init-addr for dynamic servers
Define srv.init_addr_methods to SRV_IADDR_NONE on 'add server' CLI
handler. This explicitly states that no resolution will be made on the
server creation.

This is not a real bug as the default value (SRV_IADDR_END) has the same
effect in practice. However the intent is clearer and prevent to use the
default "libc,last" by mistake which cannot execute on runtime (blocking
call + file access via gethostbyname/getaddrinfo).

The doc is also updated to reflect this limitation.

This should be backported up to 2.4.
2021-06-10 17:44:05 +02:00
Remi Tricot-Le Breton
6056e61ae2 MINOR: ssl: Add the "show ssl cert foo.pem.ocsp" CLI command
Add the ability to dump an OCSP response details through a call to "show
ssl cert cert.pem.ocsp". It can also be used on an ongoing transaction
by prefixing the certificate name with a '*'.
Even if the ckch structure holds an ocsp_response buffer, we still need
to look for the actual ocsp response entry in the ocsp response tree
rather than just dumping the ckch's buffer details because when updating
an ocsp response through a "set ssl ocsp-response" call, the
corresponding buffer in the ckch is not updated accordingly. So this
buffer, even if it is not empty, might hold an outdated ocsp response.
2021-06-10 16:44:11 +02:00
Remi Tricot-Le Breton
da968f69c7 MINOR: ssl: Add the OCSP entry key when displaying the details of a certificate
This patch adds an "OCSP Response Key" information in the output of a
"show ssl cert <certfile>" call. The key can then be used in a "show ssl
ocsp-response <key>" CLI command.
2021-06-10 16:44:11 +02:00
Remi Tricot-Le Breton
d92fd11c77 MINOR: ssl: Add new "show ssl ocsp-response" CLI command
This patch adds the "show ssl ocsp-response [<id>]" CLI command. This
command can be used to display the IDs of the OCSP tree entries along
with details about the entries' certificate ID (issuer's name and key
hash + serial number), or to display the details of a single
ocsp-response if an ID is given. The details displayed in this latter
case are the ones shown by a "openssl ocsp -respin <ocsp-response>
-text" call.
2021-06-10 16:44:11 +02:00
Remi Tricot-Le Breton
5aa1dce5ee MINOR: ssl: Keep the actual key length in the certificate_ocsp structure
The OCSP tree entry key is a serialized version of the OCSP_CERTID of
the entry which is stored in a buffer that can be at most 128 bytes.
Depending on the length of the serial number, the actual non-zero part
of the key can be smaller than 128 bytes and this new structure member
allows to know how many of the bytes are filled. It will be useful when
dumping the key (in a "show ssl cert <cert>" output for instance).
2021-06-10 16:44:11 +02:00
Christopher Faulet
12554d00f6 BUG/MEDIUM: compression: Add a flag to know the filter is still processing data
Since the commit acfd71b97 ("BUG/MINOR: http-comp: Preserve
HTTP_MSGF_COMPRESSIONG flag on the response"), there is no more flag to know
when the compression ends. This means it is possible to finish the
compression several time if there are trailers.

So, we reintroduce almost the same mechanism but with a dedicated flag. So
now, there is a bits field in the compression filter context.

The commit above is marked to be backported as far as 2.0. Thus this patch
must also be backported as far as 2.0.
2021-06-10 08:57:55 +02:00
Christopher Faulet
402740c3ad BUG/MEDIUM: compression: Properly get the next block to iterate on payload
When a DATA block is compressed, or when the compression context is finished
on a TLR/EOT block, the next block used to loop on the HTX message must be
refreshed because a defragmentation may have occurred.

This bug was introduced when the EOM block was removed in 2.4. Thus, this
patch must be backported to 2.4.
2021-06-10 08:57:55 +02:00
Christopher Faulet
86ca0e52f7 BUG/MEDIUM: compression: Fix loop skipping unused blocks to get the next block
In comp_http_payload(), the loop skipping unused blocks is buggy and may
lead to a infinite loop if the first next block is unused. Indeed instead of
iterating on blocks, we always retrieve the same one because <blk> is used
instead of <next> to get the next block.

This bug was introduced when the EOM block was removed in 2.4. Thus, this
patch must be backported to 2.4.
2021-06-10 08:57:55 +02:00
Remi Tricot-Le Breton
a3a0cce8ee BUG/MINOR: ssl: OCSP stapling does not work if expire too far in the future
The wey the "Next Update" field of the OCSP response is converted into a
timestamp relies on the use of signed integers for the year and month so
if the calculated timestamp happens to overflow INT_MAX, it ends up
being seen as negative and the OCSP response being dwignored in
ssl_sock_ocsp_stapling_cbk (because of the "ocsp->expire < now.tv_sec"
test).

It could be backported to all stable branches.
2021-06-09 17:49:00 +02:00
William Lallemand
722180aca8 BUILD: make tune.ssl.keylog available again
Since commit 04a5a44 ("BUILD: ssl: use HAVE_OPENSSL_KEYLOG instead of
OpenSSL versions") the "tune.ssl.keylog" feature is broken because
HAVE_OPENSSL_KEYLOG does not exist.

Replace this by a HAVE_SSL_KEYLOG which is defined in openssl-compat.h.
Also add an error when not built with the right openssl version.

Must be backported as far as 2.3.
2021-06-09 17:10:13 +02:00
Amaury Denoyelle
846830e47d BUG: errors: remove printf positional args for user messages context
Change the algorithm for the generation of the user messages context
prefix. Remove the dubious API relying on optional printf positional
arguments. This may be non portable, and in fact the CI glibc crashes
with the following error when some arguments are not present in the
format string :

"invalid %N$ use detected".

Now, a fixed buffer attached to the context instance is allocated once
for the program lifetime. Then call repeatedly snprintf with the
optional arguments of context if present to build the context string.
The buffer is deallocated via a per-thread free handler.

This does not need to be backported.
2021-06-08 11:40:44 +02:00
Maximilian Mader
fc0cceb08a MINOR: haproxy: Add -cc argument
This patch adds the `-cc` (check condition) argument to evaluate conditions on
startup and return the result as the exit code.

As an example this can be used to easily check HAProxy's version in scripts:

    haproxy -cc 'version_atleast(2.4)'

This resolves GitHub issue #1246.

Co-authored-by: Tim Duesterhus <tim@bastelstu.be>
2021-06-08 11:17:19 +02:00
Maximilian Mader
29c6cd7d8a CLEANUP: tools: Make errptr const in parse_line()
This change is for consistency with `cfg_eval_condition()`.
2021-06-08 10:56:10 +02:00
Tim Duesterhus
b3168b34a9 CLEANUP: cfgparse: Remove duplication of MAX_LINE_ARGS + 1
We can calculate the number of possible arguments based off the size of the
`args` array. We should do so to prevent the two values from getting out of
sync.
2021-06-08 10:54:30 +02:00
Amaury Denoyelle
5e560e80c7 MINOR: server: use ha_alert in server parsing functions
Replace memprintf usage in _srv_parse* functions by ha_alert calls. This
has the advantage to simplify the function prototype by removing an
extra char** argument.

As a consequence, the CLI handler of 'add server' is updated to output
the user messages buffers if not empty.
2021-06-07 17:19:33 +02:00
Amaury Denoyelle
9d0138ab08 MINOR: server: use parsing ctx for server init addr
Initialize the parsing context in srv_init_addr. This function is called
after configuration check.

This will standardize the stderr output on startup with the parse_server
function.
2021-06-07 17:19:30 +02:00
Amaury Denoyelle
e74cbc3227 REORG: config: use parsing ctx for server config check
Initialize the parsing context when checking server config validity.
Adjust the log messages to remove redundant config file/line and server
name. Do a similar cleaning in prepare_srv from ssl_sock as this
function is called at the same stage.

This will standardize the stderr output on startup with the parse_server
function.
2021-06-07 17:19:27 +02:00
Amaury Denoyelle
0fc136ce5b REORG: server: use parsing ctx for server parsing
Use the parsing context in parse_server. Remove redundant manual
format-string specifying the current file/line/server parsed.
2021-06-07 17:19:24 +02:00
Amaury Denoyelle
d0b237c713 MINOR: log: define server user message format
Define the format for user messages related to a server instance. It
contains the names of the backend and the server itself.
2021-06-07 17:19:23 +02:00
Amaury Denoyelle
111243003e MINOR: errors: specify prefix "config" for parsing output
Set "config :" as a prefix for the user messages context before starting
the configuration parsing. All following stderr output will be prefixed
by it.

As a consequence, remove extraneous prefix "config" already specified in
various ha_alert/warning/notice calls.
2021-06-07 17:19:16 +02:00
Amaury Denoyelle
da3d68111c MINOR: log: display exec path on first warning
Display process executable path on first warning if not already done in
ha_warning, as in ha_alert. The output is thus cleaner when ALERT and
WARN messages are mixed, with the executable path always on first
position.
2021-06-07 17:19:15 +02:00
Amaury Denoyelle
816281ff16 MINOR: errors: use user messages context in print_message
Prepend the user messages context to stderr output in print_message. It
is inserted between the output prefix (log level / pid) and the message
itself. Its content depends on the loaded context infos.
2021-06-07 17:19:10 +02:00
Amaury Denoyelle
6af81f80fb MEDIUM: errors: implement parsing context type
Create a parsing_ctx structure. This type is used to store information
about the current file/line parsed. A global context is created and
can be manipulated when haproxy is in STARTING mode. When starting is
over, the context is resetted and should not be accessed anymore.
2021-06-07 16:58:16 +02:00
Amaury Denoyelle
0a1cdccebd MINOR: log: do not discard stderr when starting is over
Always print message in ha_alert/warning/notice when starting is over,
regardless of quiet/verbose options.

This change is useful to retrieve the output via the newly implemented
user messages buffer at runtime, for the CLI handlers.
2021-06-07 16:58:16 +02:00
Amaury Denoyelle
1833e43c3e MEDIUM: errors: implement user messages buffer
The user messages buffer is used to store the stderr output after the
starting is over. Each thread has it own user messages buffer. Add some
functions to add a new message, retrieve and clear the content.

The user messages buffer primary goal is to be consulted by CLI
handlers. Each handlers using it must clear the buffer before starting
its operation.
2021-06-07 16:58:16 +02:00
Amaury Denoyelle
c008a63582 CLEANUP: server: fix cosmetic of error message on sni parsing
Fix memprintf used in server_parse_sni_expr. Error messages should not
be ending with a newline as it will be inserted in the parent function
on the ha_alert invocation.
2021-06-07 16:58:16 +02:00
Amaury Denoyelle
ce986e1ce8 REORG: errors: split errors reporting function from log.c
Move functions related to errors output on stderr from log.c to a newly
created errors.c file. It targets print_message and
ha_alert/warning/notice/diag functions and related startup_logs feature.
2021-06-07 16:58:15 +02:00
Willy Tarreau
63b3ae7ca3 CLEANUP: backend: fix incorrect comments on locking conditions for lb functions
The leastconn and roundrobin functions mention that the server's lock
must be held while this is not true at all and it is not used either.
The "first" algo doesn't mention anything about the need for locking,
so let's mention that it uses the lbprm lock.
2021-06-04 15:40:50 +02:00
Christopher Faulet
5e702fcadc MINOR: http-ana: Use -1 status for client aborts during queuing and connect
When a client aborts while the session is in the queue or during the connect
stage, instead of reporting a 503-Service-Unavailable error in logs, -1
status is used. It means -1 status is now reported with 'CC' and 'CQ'
termination state.

Indeed, when a client aborts before the server connection is established,
there is no reason to report a 503 because nothing is sent to the
server. And in this case, because it is a client abort, it is useless to
send any response to the client. Thus -1 status is approriate. This status
is used in log messages when the connection is closed and no response is
sent.

This patch should fix the issue #1266.
2021-06-02 17:17:34 +02:00
William Lallemand
f22b032956 BUILD: fix compilation for OpenSSL-3.0.0-alpha17
Some changes in the OpenSSL syntax API broke this syntax:
  #if SSL_OP_NO_TLSv1_3

OpenSSL made this change which broke our usage in commit f04bb0bce490de847ed0482b8ec9eabedd173852:

-# define SSL_OP_NO_TLSv1_3                               (uint64_t)0x20000000
+#define SSL_OP_BIT(n)  ((uint64_t)1 << (uint64_t)n)
+# define SSL_OP_NO_TLSv1_3                               SSL_OP_BIT(29)

Which can't be evaluated by the preprocessor anymore.
This patch replace the test by an openssl version test.

This fix part of #1276 issue.
2021-06-02 16:41:50 +02:00
Christopher Faulet
bf7743094e CLEANUP: mux-fcgi: Don't needlessly store result of data/trailers parsing
Return values of fcgi_strm_parse_data() and fcgi_strm_parse_trailers() are
no longer checked. Thus it is useless to store it.

This patch should fix the issues #1269 and #1268.
2021-06-02 12:04:42 +02:00
Christopher Faulet
c4439f71b0 BUG/MINOR: vars: Be sure to have a session to get checks variables
It is now possible to get any variables from the cli. Concretely, only
variables in the PROC scope can be retrieved because there is neither stream
nor session defined. But, nothing forbids anyone to try to get a variable in
any scope. No value will be found, but it is allowed. Thus, we must be sure
to not rely on an undefined session or stream in that case. Especially, the
session must be tested before retrieving variables in CHECK scope.

This patch should fix the issue #1249. It must be backported to 2.4.
2021-06-02 11:55:14 +02:00
Christopher Faulet
e9106d69cb MINOR: backend: Don't release SI endpoint anymore in connect_server()
Thanks to the previous patch (822decfd "BUG/MAJOR: stream-int: Release SI
endpoint on server side ASAP on retry"), it is now useless to release any
existing connection in connect_server() because it was already done in
back_handle_st_cer() if necessary.

This patch is not a CLEANUP because it may introduce some bugs in edge
cases. There is no reason to backport it for now except if it is required to
fix a bug.
2021-06-01 15:54:50 +02:00
Christopher Faulet
f822decfda BUG/MAJOR: stream-int: Release SI endpoint on server side ASAP on retry
When a connection attempt failed, if a retry is possible, the SI endpoint on
the server side is immediately released, instead of waiting to establish a
new connection to a server. Thus, when the backend SI is switched from
SI_ST_CER state to SI_ST_REQ, SI_ST_ASS or SI_ST_TAR, its endpoint is
released. It is expected because the SI is moved to a state prior to the
connection stage ( < SI_ST_CONN). So it seems logical to not have any server
connection.

It is especially important if the retry is delayed (SI_ST_TAR or
SI_ST_QUE). Because, if the server connection is preserved, any error at the
connection level is unexpectedly relayed to the stream, via the
stream-interface, leading to an infinite loop in process_stream(). if
SI_FL_ERR flag is set on the backend SI in another state than SI_ST_CLO, an
internal goto is performed to resync the stream-interfaces. In addtition,
some ressources are not released ASAP.

This bug is quite old and was reported 1 or 2 times per years since the 2.2
(at least) with not enough information to catch it. It must be backported as
far as 2.2 with a special care because this part has moved several times and
after some observation period and feedback from users to be sure. For info,
in 2.0 and prior, the connection is released when an error is encountered in
SI_ST_CON or SI_ST_RDY states.
2021-06-01 15:53:54 +02:00
Christopher Faulet
1a4449b0d0 CLEANUP: http-ana: Remove useless if statement about L7 retries
Thanks to the commit 1f08bffe0 ("MINOR: http-ana: Perform L7 retries because
of status codes in response analyser"), the L7 retries about the response
status code is now fully handled in the HTTP response analyser.
CF_READ_ERROR flag is no longer set on the response channel in this
case. Thus it is useless to try to catch L7 retries when CF_READ_ERROR is
set because it cannot happen.

The above commit was backported to 2.4, thus this one should also be
backported.
2021-05-31 11:45:26 +02:00
Remi Tricot-Le Breton
476462010e BUG/MINOR: proxy: Missing calloc return value check in chash_init_server_tree
A memory allocation failure happening in chash_init_server_tree while
trying to allocate a server's lb_nodes item used in consistent hashing
would have resulted in a crash. This function is only called during
configuration parsing.

It was raised in GitHub issue #1233.
It could be backported to all stable branches.
2021-05-31 10:55:51 +02:00
Remi Tricot-Le Breton
17acbab0ac BUG/MINOR: http: Missing calloc return value check in make_arg_list
A memory allocation failure happening in make_arg_list when trying to
allocate the argument list would have resulted in a crash. This function
is only called during configuration parsing.

It was raised in GitHub issue #1233.
It could be backported to all stable branches.
2021-05-31 10:51:09 +02:00
Remi Tricot-Le Breton
b6864a5b6f BUG/MINOR: http: Missing calloc return value check while parsing redirect rule
A memory allocation failure happening in http_parse_redirect_rule when
trying to allocate a redirect_rule structure would have resulted in a
crash. This function is only called during configuration parsing.

It was raised in GitHub issue #1233.
It could be backported to all stable branches.
2021-05-31 10:51:08 +02:00
Remi Tricot-Le Breton
1f4fa906c7 BUG/MINOR: worker: Missing calloc return value check in mworker_env_to_proc_list
A memory allocation failure happening in mworker_env_to_proc_list when
trying to allocate a mworker_proc would have resulted in a crash. This
function is only called during init.

It was raised in GitHub issue #1233.
It could be backported to all stable branches.
2021-05-31 10:51:06 +02:00
Remi Tricot-Le Breton
6443bcc2e1 BUG/MINOR: compression: Missing calloc return value check in comp_append_type/algo
A memory allocation failure happening in comp_append_type or
comp_append_algo called while parsing compression options would have
resulted in a crash. These functions are only called during
configuration parsing.

It was raised in GitHub issue #1233.
It could be backported to all stable branches.
2021-05-31 10:51:04 +02:00
Remi Tricot-Le Breton
8cb033643f BUG/MINOR: http: Missing calloc return value check while parsing tcp-request rule
A memory allocation failure happening in tcp_parse_request_rule while
processing the "capture" keyword and trying to allocate a cap_hdr
structure would have resulted in a crash. This function is only called
during configuration parsing.

It was raised in GitHub issue #1233.
It could be backported to all stable branches.
2021-05-31 10:51:02 +02:00
Remi Tricot-Le Breton
2ca42b4656 BUG/MINOR: http: Missing calloc return value check while parsing tcp-request/tcp-response
A memory allocation failure happening in tcp_parse_tcp_req or
tcp_parse_tcp_rep when trying to allocate an act_rule structure would
have resulted in a crash. These functions are only called during
configuration parsing.

It was raised in GitHub issue #1233.
It could be backported to all stable branches.
2021-05-31 10:51:00 +02:00
Remi Tricot-Le Breton
18a82ba690 BUG/MINOR: proxy: Missing calloc return value check in proxy_defproxy_cpy
A memory allocation failure happening in proxy_defproxy_cpy while
copying the default compression options would have resulted in a crash.
This function is called for every new proxy found while parsing the
configuration.

It was raised in GitHub issue #1233.
It could be backported to all stable branches.
2021-05-31 10:50:59 +02:00
Remi Tricot-Le Breton
55ba0d6865 BUG/MINOR: proxy: Missing calloc return value check in proxy_parse_declare
A memory allocation failure happening during proxy_parse_declare while
processing the "capture" keyword and allocating a cap_hdr structure
would have resulted in a crash. This function is only called during
configuration parsing.

It was raised in GitHub issue #1233.
It could be backported to all stable branches.
2021-05-31 10:50:57 +02:00
Remi Tricot-Le Breton
a4bf8a059d BUG/MINOR: http: Missing calloc return value check in parse_http_req_capture
A memory allocation failure happening in parse_http_req_capture while
processing a "len" keyword and allocating a cap_hdr structure would
have resulted in a crash. This function is only called during
configuration parsing.

It was raised in GitHub issue #1233.
It could be backported to all stable branches.
2021-05-31 10:50:55 +02:00
Remi Tricot-Le Breton
612b2c37be BUG/MINOR: ssl: Missing calloc return value check in ssl_init_single_engine
A memory allocation failure happening during ssl_init_single_engine
would have resulted in a crash. This function is only called during
init.

It was raised in GitHub issue #1233.
It could be backported to all stable branches.
2021-05-31 10:50:49 +02:00
Remi Tricot-Le Breton
208ff01b23 BUG/MINOR: peers: Missing calloc return value check in peers_register_table
A memory allocation failure happening during peers_register_table would
have resulted in a crash. This function is only called during init.

It was raised in GitHub issue #1233.
It could be backported to all stable branches.
2021-05-31 10:50:46 +02:00
Remi Tricot-Le Breton
f1800e64ef BUG/MINOR: server: Missing calloc return value check in srv_parse_source
Two calloc calls were not checked in the srv_parse_source function.
Considering that this function could be called at runtime through a
dynamic server creation via the CLI, this could lead to an unfortunate
crash.

It was raised in GitHub issue #1233.
It could be backported to all stable branches even though the runtime
crash could only happen on branches where dynamic server creation is
possible.
2021-05-31 10:50:32 +02:00
Tim Duesterhus
5546c8bdce MINOR: cfgparse: Fail when encountering extra arguments in macro
This resolves GitHub issue #1124.

This change should be backported as a *warning* to 2.4.
2021-05-27 07:54:21 +02:00
Christopher Faulet
1f08bffe0c MINOR: http-ana: Perform L7 retries because of status codes in response analyser
L7 retries because of status codes are now performed in the response
analyser. This way, it is no longer required to handle L7 retries in
si_cs_recv(). It is also useless to set CF_READ_ERROR on the response
channel to be able to trigger such retries.

In addition, if no L7 retries are performed when the response is received,
the L7 buffer is immediately released. Before in this case, it was only
released with the stream.
2021-05-26 13:56:06 +02:00
Christopher Faulet
d976923ab2 BUG/MINOR: http-ana: Handle L7 retries on refused early data before K/A aborts
When a network error occurred on the server side, if it is not the first
request (in case of keep-alive), nothing is returned to the client and its
connexion is closed to be sure it may retry. However L7 retries on refused
early data (0rtt-rejected) must be performed first.

In addition, such L7 retries must also be performed before incrementing the
failed responses counter.

This patch must be backported as far as 2.0.
2021-05-26 13:56:06 +02:00
Christopher Faulet
552601d5fd BUG/MINOR: http-ana: Send the right error if max retries is reached on L7 retry
This bug was introduced by the previous commit (9f5382e45 Revert "MEDIUM:
http-ana: Deal with L7 retries in HTTP analysers") because I failed the
revert.

On L7 retry, if the maximum connection retries is reached, an error must be
return to the client. Depending the situation, it may be a 502-Bad-Gateway
(empty-response or junk-response), a 504-Gateway-Timeout (response-timeout)
or a 425-Too-Early (0rtt-rejected). But contrary to what the comment says,
the do_l7_retry() function always returns a success.

Note it is not a problem for L7 retries on the response status code because
the stream-interface already takes care to have not reached the maximum
connection retries counter to trigger a L7 retry.

This patch must be backported to 2.4 because the commit must also be
backported to 2.4.
2021-05-26 10:31:11 +02:00
Christopher Faulet
9f5382e452 Revert "MEDIUM: http-ana: Deal with L7 retries in HTTP analysers"
This reverts commit 5b82cc5b5c. The purpose of
this commit was to fully handle L7 retries in HTTP analysers and stop to
deal with the L7 buffer in si_cs_send()/si_cs_recv(). It is of course
cleaner this way. But there is a huge drawback. The L7 buffer is reserved
from the time the request analysis is finished until the moment the response
is received. For a small request, the analysis is finished before the
connection to the server. Thus for the L7 buffer will be kept for queued
sessions while it is not mandatory.

So, for now, the commit is reverted to go back to the less expensive
solution. This patch must be backported to 2.4.
2021-05-25 10:51:20 +02:00
Christopher Faulet
44c0dcfe90 CLEANUP: mux-h1: Rename functions parsing input buf and filling output buf
Main functions are renamed h1_process_demux() and h1_process_mux() to be
consistent with the H2 mux. For the same reason,
h1_process_header/data/tralers) functions, responsible to parse incoming
data are renamed with "h1_handle_" prefix.
2021-05-25 10:41:50 +02:00
Christopher Faulet
00d7cde551 MINOR: muxes/h1-htx: Realign input buffer using b_slow_realign_ofs()
Input buffers have never output data. So, use b_slow_realign_ofs() function
instead of b_slow_realign(). It is a slighly simpler function. And in the H1
mux, it allows a realign by setting the input buffer head to permit
zero-copies.
2021-05-25 10:41:50 +02:00
Christopher Faulet
7a835f3cb0 MINOR: h1-htx: Use a correlation table to speed-up small chunks parsing
Instead of using hex2i() to convert an hexa digit to an integer in the
function parsing small chunks, we now use a table because it is faster.
2021-05-25 10:41:50 +02:00
Christopher Faulet
bdcefe58b7 MEDIUM: h1-htx: Add a function to parse contiguous small chunks
Add h1_parse_full_contig_chunks() function to parse full contiguous chunks.
This function neither handles incomplete chunks nor wrapping buffers. It is
designed to efficiently parse a buffer with several small chunks. Of course,
there is no zero copy here because it is not possible. This function is a
bit tricky and all changes may a have a impact. This one may probably be
optimized, but it is good enough for now and not too complex.

The main function (h1_parse_msg_chunks) always tries to use this function
when the HTTP parser is waiting for a chunk size. In this case, there is no
zero-copy, so there is no reason to call the generic version to parse the
chunk. However, if some unparsed data remain after this step, the generic
function is called. This way, wrapping data and incomplete chunks may be
parsed.

Quick tests show it is now slightly faster in all cases than the legacy
mode.
2021-05-25 10:41:50 +02:00
Christopher Faulet
0d4c924c34 MEDIUM: h1-htx: Split function to parse a chunk and the loop on the buffer
A generic function is now used to only parse the current chunk (h1_parse_chunk)
and the main one (h1_parse_msg_chunks) is used to loop on the buffer and relies
on the first one. This change is mandatory to be able to use an optimized
function to parse contiguous small chunks.
2021-05-25 10:41:50 +02:00
Christopher Faulet
140691baf9 MINOR: h1-htx: Move HTTP chunks parsing into a dedicated function
Chunked data are now parsed in a dedicated function. This way, it will be
possible to have two functions to parse chunked messages. The current one
for messages with large chunks and an other one to parse messages with small
chunks.

The parsing of small chunks is really sensitive because it may be used as a
DoS attack. So we must be carefull to have an optimized function to parse
such messages.
2021-05-25 10:41:50 +02:00
Christopher Faulet
16a524c9ea MINOR: mux-h1/mux-fcgi: Don't needlessly loop on data parsing
Because the function parsing H1 data is now able to handle wrapping input
buffers, there is no reason to loop anymore in the muxes to be sure to parse
wrapping data.
2021-05-25 10:41:50 +02:00
Christopher Faulet
f7c2044f8f MEDIUM: h1-htx: Adapt H1 data parsing to copy wrapping data in one call
Since the beginning, wrapping input data are parsed and copied in 2 steps to
not deal with the wrapping in H1 parsing functions. But there is no reason
to do so. This needs 2 calls to parsing functions. This also means, most of
time, when the input buffer does not wrap, there is an extra call for
nothing.

Thus, now, the data parsing functions try to copy as much data as possible,
handling wrapping buffer if necessary.
2021-05-25 10:41:50 +02:00
Christopher Faulet
de471a4a8d MINOR: h1-htx: Update h1 parsing functions to return result as a size_t
h1 parsing functions (h1_parse_msg_*) returns the number of bytes parsed or
0 if nothing is parsed because an error occurred or some data are
missing. But they never return negative values. Thus, instead of a signed
integer, these function now return a size_t value.

The H1 and FCGI muxes are updated accordingly. Note that h1_parse_msg_data()
has been slightly adapted because the parsing of chunked messages still need
to handle negative values when a parsing error is reported by
h1_parse_chunk_size() or h1_skip_chunk_crlf().
2021-05-25 10:41:50 +02:00
Dragan Dosen
a75eea78e2 MINOR: map/acl: print the count of all the map/acl entries in "show map/acl"
The output of "show map/acl" now contains the 'entry_cnt' value that
represents the count of all the entries for each map/acl, not just the
active ones, which means that it also includes entries currently being
added.
2021-05-25 08:44:45 +02:00
Christopher Faulet
acfd71b97a BUG/MINOR: http-comp: Preserve HTTP_MSGF_COMPRESSIONG flag on the response
This flag is set on the response when its payload is compressed by HAProxy.
It must be preserved because it may be used when the log message is emitted.

When the compression filter was refactored to support the HTX, an
optimization was added to not perform extra proessing on the trailers.
HTTP_MSGF_COMPRESSIONG flag is removed when the last data block is
compressed. It is not required, it is just an optimization and unfortunately
a bug. This optimization must be removed to preserve the flag.

This patch must be backported as far as 2.0. On the HTX is affected.
2021-05-21 09:59:00 +02:00
Christopher Faulet
a6d3704e38 BUG/MEDIUM: filters: Exec pre/post analysers only one time per filter
For each filter, pre and post callback functions must only be called one
time. To do so, when one of them is finished, the corresponding analyser bit
must be removed from pre_analyzers or post_analyzers bit field. It is only
an issue with pre-analyser callback functions if the corresponding analyser
yields. It may happens with lua action for instance. In this case, the
filters pre analyser callback function is unexpectedly called several times.

This patch should fix the issue #1263. It must be backported is all stable
versions.
2021-05-21 09:59:00 +02:00
Amaury Denoyelle
79a88ba3d0 BUG/MAJOR: server: prevent deadlock when using 'set maxconn server'
A deadlock is possible with 'set maxconn server' command, if there is
pending connection ready to be dequeued. This is caused by the locking
of server spinlock in both cli_parse_set_maxconn_server and
process_srv_queue.

Fix this by reducing the scope of the server lock into
server_parse_maxconn_change_request. If connection are dequeued, the
lock is taken a second time. This can be seen as suboptimal but as it
happens only during 'set maxconn server' it can be considered as
tolerable.

This issue was reported on the mailing list, for the 1.8.x branch.
It must be backported up to the 1.8.
2021-05-19 17:52:05 +02:00
Remi Tricot-Le Breton
a6b2784099 CLEANUP: ssl: Fix coverity issues found in CA file hot update code
Coverity found a few uninitialized values and some dead code in the
CA/CRL file hot update code as well as a missing return value check.
2021-05-18 10:52:54 +02:00
Remi Tricot-Le Breton
18c7d83934 BUILD/MINOR: ssl: Fix compilation with OpenSSL 1.0.2
The following functions used in CA/CRL file hot update were not defined
in OpenSSL 1.0.2 so they need to be defined in openssl-compat :
- X509_CRL_get_signature_nid
- X509_CRL_get0_lastUpdate
- X509_CRL_get0_nextUpdate
- X509_REVOKED_get0_serialNumber
- X509_REVOKED_get0_revocationDate
2021-05-18 00:28:31 +02:00
Remi Tricot-Le Breton
d75b99e69c BUILD/MINOR: ssl: Fix compilation with SSL enabled
The CA/CRL hot update patches did not compile on some targets of the CI
(mainly gcc + ssl). This patch should fix almost all of them. It adds
missing variable initializations and return value checks to the
BIO_reset calls in show_crl_detail.
2021-05-17 11:53:21 +02:00
Remi Tricot-Le Breton
51e28b6bee MEDIUM: ssl: Add "show ssl crl-file" CLI command
This patch adds the "show ssl crl-file [<crlfile>]" CLI command. This
command can be used to display the list of all the known CRL files when
no specific file name is specified, or to display the details of a
specific CRL file when a name is given.
The details displayed for a specific CRL file are inspired by the ones
shown by a "openssl crl -text -noout -in <filename>".
2021-05-17 10:50:24 +02:00
Remi Tricot-Le Breton
eef8e7b8bc MINOR: ssl: Add "abort ssl crl-file" CLI command
The "abort" command aborts an ongoing transaction started by a "set ssl
crl-file" command. Since the updated CRL file data is not pushed into
the CA file tree until a "commit ssl crl-file" call is performed, the
abort command simply deleted the new cafile_entry (storing the new CRL
file data) stored in the transaction.
2021-05-17 10:50:24 +02:00
Remi Tricot-Le Breton
720e3b9f33 MEDIUM: ssl: Add "new+del crl-file" CLI commands
This patch adds the "new ssl crl-file" and "del ssl crl-file" CLI
commands.
The "new" command can be used to create a new empty CRL file that can be
filled in thanks to a "set ssl crl-file" command. It can then be used in
a new crt-list line.
The newly created CRL file is added to the CA file tree so any call to
"show ssl crl-file" will display its name.
The "del" command allows to delete an unused CRL file. A CRL file will
be considered unused if its list of ckch instances is empty. It does not
work on an uncommitted CRL file transaction created via a "set ssl
crl-file" command call.
2021-05-17 10:50:24 +02:00
Remi Tricot-Le Breton
a51b339d95 MEDIUM: ssl: Add "set+commit ssl crl-file" CLI commands
This patch adds the "set ssl crl-file" and "commit ssl crl-file"
commands, following the same logic as the certificate and CA file update
equivalents.
When trying to update a Certificate Revocation List (CRL) file via a
"set" command, we start by looking for the entry in the CA file tree and
then building a new cafile_entry out of the payload, without adding it
to the tree yet. It will only be added when a "commit" command is
called.
During a "commit" command, we insert the newly built cafile_entry in the
CA file tree while keeping the previous entry. We then iterate over all
the instances that used the CRL file and rebuild a new one and its
dedicated SSL context for every one of them.
When all the contexts are properly created, the old instances get
replaced by the new ones and the old CRL file is removed from the tree.
2021-05-17 10:50:24 +02:00
Remi Tricot-Le Breton
f81c70ceec MINOR: ssl: Chain instances in ca-file entries
In order for crl-file hot update to be possible, we need to add an extra
link between the CA file tree entries that hold Certificate Revocation
Lists and the instances that use them. This way we will be able to
rebuild each instance upon CRL modification.
This mechanism is similar to what was made for the actual CA file update
since both the CA files and the CRL files are stored in the same CA file
tree.
2021-05-17 10:50:24 +02:00
Remi Tricot-Le Breton
c3a8477776 MINOR: ssl: Add "del ssl ca-file" CLI command
This patch adds the "del ssl ca-file <cafile>" CLI command which can be
used to delete an unused CA file.
The CA file will be considered unused if its list of ckch instances is
empty. This command cannot be used to delete the uncommitted CA file of
a previous "set ssl ca-file" without commit. It only acts on
CA file entries already inserted in the CA file tree.

This fixes a subpart of GitHub issue #1057.
2021-05-17 10:50:24 +02:00
Remi Tricot-Le Breton
9f40fe0202 MEDIUM: ssl: Add "new ssl ca-file" CLI command
This patch adds the "new ssl ca-file <cafile>" CLI command. This command
can be used to create a new empty CA file that can be filled in thanks
to a "set ssl ca-file" command. It can then be used in a new crt-list
line.
The newly created CA file is added directly in the cafile tree so any
following "show ssl ca-file" call will display its name.

This fixes a subpart of GitHub issue #1057.
2021-05-17 10:50:24 +02:00
Remi Tricot-Le Breton
2a22e16cb8 MEDIUM: ssl: Add "show ssl ca-file" CLI command
This patch adds the "show ssl ca-file [<cafile>[:index]]" CLI command.
This command can be used to display the list of all the known CA files
when no specific file name is specified, or to display the details of a
specific CA file when a name is given. If an index is given as well, the
command will only display the certificate having the specified index in
the CA file (if it exists).
The details displayed for each certificate are the same as the ones
showed when using the "show ssl cert" command on a single certificate.

This fixes a subpart of GitHub issue #1057.
2021-05-17 10:50:24 +02:00
Remi Tricot-Le Breton
523f0e483a MINOR: ssl: Refactorize the "show certificate details" code
Move all the code that dumps the details of a specific certificate into
a dedicated function so that it can be used elsewhere.
2021-05-17 10:50:24 +02:00
Remi Tricot-Le Breton
0bb482436c MINOR: ssl: Add a cafile_entry type field
The CA files and CRL files are stored in the same cafile_tree so this
patch adds a new field the the cafile_entry structure that specifies the
type of the entry. Since a ca-file can also have some CRL sections, the
type will be based on the option used to load the file and not on its
content (ca-file vs crl-file options).
2021-05-17 10:50:24 +02:00
Remi Tricot-Le Breton
d5fd09d339 MINOR: ssl: Add "abort ssl ca-file" CLI command
The "abort" command aborts an ongoing transaction started by a "set ssl
ca-file" command. Since the updated CA file data is not pushed into the
cafile tree until a "commit ssl ca-file" call is performed, the abort
command simply clears the new cafile_entry that was stored in the
cafile_transaction.

This fixes a subpart of GitHub issue #1057.
2021-05-17 10:50:24 +02:00
Remi Tricot-Le Breton
a32a68bd3b MEDIUM: ssl: Add "set+commit ssl ca-file" CLI commands
This patch adds the "set ssl ca-file" and "commit ssl ca-file" commands,
following the same logic as the certificate update equivalents.
When trying to update a ca-file entry via a "set" command, we start by
looking for the entry in the cafile_tree and then building a new
cafile_entry out of the given payload. This new object is not added to
the cafile_tree until "commit" is called.
During a "commit" command, we insert the newly built cafile_entry in the
cafile_tree, while keeping the previous entry as well. We then iterate
over all the instances linked in the old cafile_entry and rebuild a new
ckch instance for every one of them. The newly inserted cafile_entry is
used for all those new instances and their respective SSL contexts.
When all the contexts are properly created, the old instances get
replaced by the new ones and the old cafile_entry is removed from the
tree.

This fixes a subpart of GitHub issue #1057.
2021-05-17 10:50:24 +02:00
Remi Tricot-Le Breton
bfadc02f34 MINOR: ssl: Ckch instance rebuild and cleanup factorization in CLI handler
The process of rebuilding a ckch_instance when a certificate is updated
through a cli command will be roughly the same when a ca-file is updated
so this factorization will avoid code duplication.
2021-05-17 10:50:24 +02:00
Remi Tricot-Le Breton
38c999b11c MINOR: ssl: Add helper function to add cafile entries
Adds a way to insert a new uncommitted cafile_entry in the tree. This
entry will be the one fetched by any lookup in the tree unless the
oldest cafile_entry is explicitely looked for. This way, until a "commit
ssl ca-file" command is completed, there could be two cafile_entries
with the same path in the tree, the original one and the newly updated
one.
2021-05-17 10:50:24 +02:00
Remi Tricot-Le Breton
383fb1472e MEDIUM: ssl: Add a way to load a ca-file content from memory
The updated CA content coming from the CLI during a ca-file update will
directly be in memory and not on disk so the way CAs are loaded in a
cafile_entry for now (via X509_STORE_load_locations calls) cannot be
used.
This patch adds a way to fill a cafile_entry directly from memory and to
load the contained certificate and CRL sections into an SSL store.
CRL sections are managed as well as certificates in order to mimic the
way CA files are processed when specified in an option. Indeed, when
parsing a CA file given through a ca-file or ca-verify-file option, we
iterate over the different sections in ssl_set_cert_crl_file and load
them regardless of their type. This ensures that a file that was
properly parsed when given as an option will also be accepted by the
CLI.
2021-05-17 10:50:24 +02:00
Remi Tricot-Le Breton
5daff3c8ab MINOR: ssl: Add helper functions to create/delete cafile entries
Add ssl_store_create_cafile_entry and ssl_store_delete_cafile_entry
functions.
2021-05-17 10:50:24 +02:00
Remi Tricot-Le Breton
40ddea8222 MINOR: ssl: Add reference to default ckch instance in bind_conf
In order for the link between the cafile_entry and the default ckch
instance to be built, we need to give a pointer to the instance during
the ssl_sock_prepare_ctx call.
2021-05-17 10:50:24 +02:00
Remi Tricot-Le Breton
4458b9732d MEDIUM: ssl: Chain ckch instances in ca-file entries
Each ca-file entry of the tree will now hold a list of the ckch
instances that use it so that we can iterate over them when updating the
ca-file via a cli command. Since the link between the SSL contexts and
the CA file tree entries is only built during the ssl_sock_prepare_ctx
function, which are called after all the ckch instances are created, we
need to add a little post processing after each ssl_sock_prepare_ctx
that builds the link between the corresponding ckch instance and CA file
tree entries.
In order to manage the ca-file and ca-verify-file options, any ckch
instance can be linked to multiple CA file tree entries and any CA file
entry can link multiple ckch instances. This is done thanks to a
dedicated list of ckch_inst references stored in the CA file tree
entries over which we can iterate (during an update for instance). We
avoid having one of those instances go stale by keeping a list of
references to those references in the instances.
When deleting a ckch_inst, we can then remove all the ckch_inst_link
instances that reference it, and when deleting a cafile_entry, we
iterate over the list of ckch_inst reference and clear the corresponding
entry in their own list of ckch_inst_link references.
2021-05-17 10:50:24 +02:00
Remi Tricot-Le Breton
9f0c936057 MINOR: ssl: Allow duplicated entries in the cafile_tree
In order to ease ca-file hot update via the CLI, the ca-file tree will
need to allow duplicate entries for a given path. This patch simply
enables it and offers a way to select either the oldest entry or the
latest entry in the tree for a given path.
2021-05-17 10:50:24 +02:00
Remi Tricot-Le Breton
af8820a9a5 CLEANUP: ssl: Move ssl_store related code to ssl_ckch.c
This patch moves all the ssl_store related code to ssl_ckch.c since it
will mostly be used there once the CA file update CLI commands are all
implemented. It also makes the cafile_entry structure visible as well as
the cafile_tree.
2021-05-17 10:50:24 +02:00
Willy Tarreau
fb601956db BUILD: sample: use strtoll() instead of atoll()
atoll() is not portable, but strtoll() is more common. We must pass NULL
to the end pointer however since the parser must consume digits and stop
at the first non-digit char. No backport is needed as this was introduced
in 2.4-dev17 with commit 51c8ad45c ("MINOR: sample: converter: Add json_query
converter").
2021-05-14 08:51:53 +02:00
Willy Tarreau
388fc25915 IMPORT: slz: use inttypes.h instead of stdint.h
stdint.h is not as portable as inttypes.h. It doesn't exist at least
on AIX 5.1 and Solaris 7, while inttypes.h is present there and does
include stdint.h on platforms supporting it.

This is equivalent to libslz upstream commit e36710a ("slz: use
inttypes.h instead of stdint.h")
2021-05-14 08:44:52 +02:00
Willy Tarreau
6bfc10c392 BUILD: config: avoid a build warning on numa_detect_topology() without threads
The function is defined when using linux+cpu affinity but is only used
if threads are enabled, so let's add this condition to avoid aa build
warning about an unused function when building with thread disabled.
This came in 2.4-dev17 with commit b56a7c89a ("MEDIUM: cfgparse: detect
numa and set affinity if needed") so no backport is needed.
2021-05-14 08:30:46 +02:00
Willy Tarreau
26f42a0779 BUG/MAJOR: config: properly initialize cpu_map.thread[] up to MAX_THREADS
A mistake was introduced in 2.4-dev17 by commit 982fb5339 ("MEDIUM:
config: use platform independent type hap_cpuset for cpu-map"), it
initializes cpu_map.thread[] from 0 to MAX_PROCS-1 instead of
MAX_THREADS-1 resulting in crashes when the two differ, e.g. when
building with USE_THREAD= but still with USE_CPU_AFFINITY=1.

No backport is needed.
2021-05-14 08:26:38 +02:00
Willy Tarreau
89f6dedf48 BUG/MINOR: lua/vars: prevent get_var() from allocating a new name
Variable names are stored into a unified list that helps compare them
just based on a pointer instead of duplicating their name with every
variable. This is convenient for those declared in the configuration
but this started to cause issues with Lua when random names would be
created upon each access, eating lots of memory and CPU for lookups,
hence the work in 2.2 with commit 4e172c93f ("MEDIUM: lua: Add
`ifexist` parameter to `set_var`") to address this.

But there remains a corner case with get_var(), which also allocates
a new variables. After a bit of thinking and discussion, it never
makes sense to allocate a new variable name on get_var():
  - if the name exists, it will be returned ;
  - if it does not exist, then the only way for it to appear will
    be that some code calls set_var() on it
  - a call to get_var() after a careful set_var(ifexist) ruins the
    effort on set_var().

For this reason, this patch addresses this issue by making sure that
get_var() will never cause a variable to be allocated. This is done
by modifying vars_get_by_name() to always call register_name() with
alloc=0, since vars_get_by_name() is exclusively used by Lua and the
new CLI's "get/set var" which also benefit from this protection.

It probably makes sense to backport this as far as 2.2 after some
observation period and feedback from users.

For more context and discussions about the issues this was causing,
see https://www.mail-archive.com/haproxy@formilux.org/msg40451.html
and in issue #664.
2021-05-13 13:44:32 +02:00
Willy Tarreau
832e242b1f DEBUG: ssl: export ssl_sock_close() to see its symbol resolved in profiling
This function is one of the few high-profile, unresolved ones in the memory
profile output, let's have it resolve to ease matching of SSL allocations,
which are not easy to follow.
2021-05-13 10:11:03 +02:00
Willy Tarreau
f1c8a3846c MINOR: activity/cli: optionally support sorting by address on "show profiling"
"show profiling" by default sorts by usage/counts, which is suitable for
occasional use. But when called from scripts to monitor/search variations,
this is not very convenient. Let's add a new "byaddr" option to support
sorting the output by address. It also eases matching alloc/free calls
from within a same library, or reading grouped tasks costs by library.
2021-05-13 10:00:17 +02:00
Willy Tarreau
973a937c5f BUG/MINOR: stats: fix lastchk metric that got accidently lost
Commit d3a9a4992 ("MEDIUM: stats: allow to select one field in
`stats_fill_sv_stats`") left one occurrence of a direct assignment
of stats[] instead of placing it into the <metric> variable, and it
was on ST_F_CHECK_STATUS. This resulted in the field being overwritten
with an empty one immediately after being set in stats_fill_sv_stats()
and the field to appear empty on the stats page.

No backport is needed as this was only for 2.4.
2021-05-12 17:50:16 +02:00
Willy Tarreau
4263f68b65 CLEANUP: stick-table: remove a leftover of an old keyword declaration
There was a leftover of an antique declaration commented out that has
now been superseded by new ones, let's remove it.
2021-05-12 17:50:16 +02:00
Amaury Denoyelle
c460c70ab7 BUG/MEDIUM: stick_table: fix crash when using tcp smp_fetch_src
Since the introduction of bc_src, smp_fetch_src from tcp_sample inspect
the kw argument to choose between the frontend or the backend source
address. However, for the stick tables, the argument is left to NULL.
This causes a segfault.

Fix the crash by explicitely set the kw argument to "src" to retrieve
the source address of the frontend side.

This bug was introduced by the following commit :
  7d081f02a4
  MINOR: tcp_samples: Add samples to get src/dst info of the backend connection

It does not need a backport as it is integrated in the current 2.4-dev
branch.

To reproduce the crash, I used the following config :

frontend fe
	bind :20080
	http-request track-sc0 src table foo
	http-request reject if { src_conn_rate(foo) gt 10 }
	use_backend h1

backend foo
	stick-table type ip size 200k expire 30s store conn_rate(60s)

backend h1
	server nginx 127.0.0.1:30080 check

This should fix the github issue #1247.
2021-05-12 15:30:03 +02:00
Willy Tarreau
9e274280a4 IMPORT: slz: do not produce the crc32_fast table when CRC is natively supported
On ARM with native CRC support, no need to inflate the executable with
a 4kB CRC table, let's just drop it.

This is slz upstream commit d8715db20b2968d1f3012a734021c0978758f911.
2021-05-12 09:29:33 +02:00
Willy Tarreau
027fdcb168 IMPORT: slz: use the generic function for the last bytes of the crc32
This is the only place where we conditionally use the crc32_fast table,
better call the crc32_char inline function for this. This should also
reduce by ~1kB the L1 cache footprint of the compression when dealing
with small blocks, and at least shows a consistent 0.5% perf improvement.

This is slz upstream commit 075351b6c2513b548bac37d6582e46855bc7b36f.
2021-05-12 09:29:29 +02:00
Tim Duesterhus
dec1c36b3a MINOR: uri_normalizer: Add fragment-encode normalizer
This normalizer encodes '#' as '%23'.

See GitHub Issue #714.
2021-05-11 17:24:32 +02:00
Tim Duesterhus
c9e05ab2de MINOR: uri_normalizer: Add fragment-strip normalizer
This normalizer strips the URI's fragment component which should never be sent
to the server.

See GitHub Issue #714.
2021-05-11 17:23:46 +02:00
Tim Duesterhus
2f413136e9 BUG/MINOR: http_act: Fix normalizer names in error messages
These places were forgotten when the normalizers were renamed.

Bug introduced in 5be6ab269e, which is 2.4.
No backport needed.
2021-05-11 17:21:53 +02:00
Willy Tarreau
da7f11bfb5 CLEANUP: pattern: remove the unused and dangerous pat_ref_reload()
This function was not used anymore after the atomic updates were
implemented in 2.3, and it must not be used given that it does not
yield and can easily make the process hang for tens of seconds on
large acls/maps. Let's remove it before someone uses it as an
example to implement something else!
2021-05-11 16:49:55 +02:00
Willy Tarreau
f5fb858bb7 MINOR: memprof: also report the totals and delta alloc-free
Already had to perform too many additions by external scripts, it's
time to add the totals and delay alloc-free as a last line in the
output of the "show memory profiling".
2021-05-11 14:21:18 +02:00
Willy Tarreau
616491b7f7 MINOR: memprof: also report the method used by each call
This was planned but missing in the previous attempt, we really need to
see what is used at each place, especially due to realloc(). Now we
print the function used in front of the caller's address, as well as
the average alloc/free size per call.
2021-05-11 14:14:30 +02:00
Willy Tarreau
79acefa749 BUG/MINOR: memprof: properly account for differences for realloc()
The realloc() function checks if the size grew or reduced in order to
count an allocation or a free, but it does so with the absolute (new
or old) value instead of the difference, resulting in realloc() often
being credited for allocating too much.

No backport is needed.
2021-05-11 09:12:56 +02:00
Ilya Shipitsin
3df5989960 CLEANUP: assorted typo fixes in the code and comments
This is 23rd iteration of typo fixes
2021-05-10 23:05:08 +02:00
Daniel Corbett
67b3cefea3 CLEANUP: cli/activity: Remove double spacing in set profiling command
It was found that when viewing the help output from the CLI that
"set profiling" had 2 spaces in it, which was pushing it out from
the rest of similar commands.

i.e. it looked like this:
  prepare acl <acl>
  prepare map <acl>
  set  profiling  <what>  {auto|on|off}
  set dynamic-cookie-key backend <bk> <k>
  set map <map> [<key>|#<ref>] <value>
  set maxconn frontend <frontend> <value>

This patch removes all of the double spaces within the command and
unifies them to single spacing, which is what is observed within the
rest of the commands.
2021-05-10 22:29:12 +02:00
Amaury Denoyelle
c89d5337ee BUG/MINOR: http_fetch: fix possible uninit sockaddr in fetch_url_ip/port
Check the return value of url2sa in smp_fetch_url_ip/port. If negative,
the address result is uninitialized and the sample fetch is aborted.
Also, the sockaddr is prelimiary zero'ed before calling url2sa to ensure
that it is not used by upper functions even if the sample returns 0.

Without the check, the value returned by the url_ip/url_port fetches is
unspecified. This can be triggered with the following curl :
$ curl -iv --request-target "xxx://127.0.0.1:20080/" http://127.0.0.1:20080/

This should be backported to all stable branches. However, note that
between the 1.8 and 2.0, the targetted functions have been extracted
from proto_http.c to http_fetch.c.

This should fix in part coverity report from the github issue #1244.
2021-05-10 14:48:55 +02:00
Willy Tarreau
5db446d7e1 BUILD: cli: appease a null-deref warning in cli_gen_usage_msg()
The compiler sees the possibility of null-deref for which a path is
possible but which doesn't exist as we didn't pass a null args outside
of the help request. The test was introduced by the simplified test on
ishelp variable, so let's add it to shut the warning.
2021-05-10 07:47:05 +02:00
Willy Tarreau
7deb28ce65 BUG/MEDIUM: quic: fix null deref on error path in qc_conn_init()
When ctx is NULL, we go to the "err" label, which could dereference it.
No backport is needed.
2021-05-10 07:40:27 +02:00
Willy Tarreau
4a75328485 BUILD: memprof: make the old caller pointer a const in get_prof_bin()
It's a const void* in the target, we can't use a void* in the caller,
this causes a build warning with clang.
2021-05-09 23:18:50 +02:00
Willy Tarreau
23c740ea51 CLEANUP: cli/mworker: properly align the help messages
CLI help commands were re-aligned by commit b205bfdab but the
master-worker ones were not done, let's do it now.
2021-05-09 22:49:44 +02:00
Willy Tarreau
92fbbcc4c6 MINOR: cli: sort the output of the "help" keywords
It's still very difficult to find all commands starting with a given
keyword like "set", "show" etc. Let's sort the lines by usage message,
this is much more convenient.
2021-05-09 22:39:07 +02:00
Willy Tarreau
0b1b830e88 MINOR: cli: make "help" support a command in argument
With ~100 commands on the CLI, it's particularly difficult to find a
specific one in the "help" output. The function used to display the
help already supports filtering on certain commands, so in the end it's
just needed to pass the argument of the help command to enable the
automatic filtering. That's what this patch does so that "help clear"
only lists commands starting with "clear" and that "help map" lists
commands containing "map" in them.
2021-05-09 20:59:23 +02:00
Willy Tarreau
2a8a2f0223 BUILD: ssl: define HAVE_CRYPTO_memcmp() based on the library version
The build fails on versions older than 1.0.1d which is the first one
introducing CRYPTO_memcmp(), so let's have a define for this instead
of enabling it whenever USE_OPENSSL is set. One could also wonder why
we're relying on openssl for such a trivial thing, and a simple local
implementation could also allow to restore lexicographic ordering.
2021-05-09 12:10:36 +02:00
Willy Tarreau
48584645fb BUILD: http_fetch: address a few aliasing warnings with older compilers
gcc-4.4 complains about aliasing in smp_fetch_url_port() and
smp_fetch_url_ip() because the local addr variable is casted to sturct
sockaddr_in before being checked. The family should be checked on the
sockaddr_storage and we have a function to retrieve the port.
The compiler still sees some warnings but these ones are OK now.
2021-05-09 10:32:54 +02:00
Willy Tarreau
b2475a139e MINOR: tools/rnd: compute the result outside of the CAS loop
ha_random64() uses a DWCAS loop to produce the random, but it computes
the resulting value inside the loop while it doesn't change upon success,
so this is a needless overhead inside the critcal path that participates
to making threads fail the race and try again. Let's take the value out
of the loop.
2021-05-09 10:26:14 +02:00
Willy Tarreau
714f34580e DOC: fix a few remainig cases of "Haproxy" and "HAproxy" in doc and comments
Some of the Lua doc and a few places still used "Haproxy" or "HAproxy".
There was even one "HA proxy". A few of them were in an example of VTest
output, indicating that VTest ought to be fixed as well. No big deal but
better address all the remaining ones so that these inconsistencies stop
spreading around.
2021-05-09 06:50:46 +02:00
Willy Tarreau
64975cf2a4 MEDIUM: mailers: use "HAProxy" nor "HAproxy" in the subject of messages
It seems to be the last visible casing inconsistency, but better address
it for completeness otherwise we'll always have to deal with some
exceptions.
2021-05-09 06:45:16 +02:00
Willy Tarreau
a5357cdfa5 MINOR: version: report "HAProxy" not "HA-Proxy" in the version output
When running "haproxy -v", we still get "HA-Proxy" which is the last
place where this confusing oddity happens. Being so used to it I didn't
even notice it until it was reported to me just after 2.2 but it never
got fixed, despite the PRODUCT_NAME macro that is used to report the
name in the stats page and in "show info" being already set to "HAProxy"
15 years ago in 1.2.14 with commit e03312613. It's about time to
uniformize everything.
2021-05-09 06:14:25 +02:00
Willy Tarreau
c28aab05d8 BUILD: fd: include log.h from fd.c
It's needed for ha_alert() and the header was missing.
2021-05-08 20:35:39 +02:00
Willy Tarreau
202f93d885 BUILD: comp: include proxy.h from flt_http_comp.c
It's used for proxy_type_str() but the header was missing.
2021-05-08 20:35:39 +02:00
Willy Tarreau
11bd6f7296 BUILD: thread: include log.h from thread.c
It's needed for ha_alert(). Probably that a separate file for error
reporting at boot would be useful.
2021-05-08 20:35:39 +02:00
Willy Tarreau
d1dd2500f2 BUILD: http-rules: include proxy.h from http_rules.c
Many proxy functions are called there but the include was missing and
inherited via cfgparse.h.
2021-05-08 20:35:39 +02:00
Willy Tarreau
5958c43271 BUILD: listener: include proxy.h from listener.c
Many proxy functions are called there but the include was missing and
inherited via cfgparse.h.
2021-05-08 20:35:39 +02:00
Willy Tarreau
c5396bd673 BUILD: mux-fcgi: include proxy.h from mux-fcgi.c
proxy_capture_error() was called there without the include, which was
inherited via cfgparse.h.
2021-05-08 20:35:39 +02:00
Willy Tarreau
adc0240147 BUILD: mux-h1: include proxy.h from mux-h1.c
proxy_capture_error() was called there without the include, which was
inherited via cfgparse.h.
2021-05-08 20:35:39 +02:00
Willy Tarreau
3d6ee407e7 BUILD: hlua: include proxy.h from hlua.c
Many proxy functions are called there but the include was missing and
inherited via cfgparse.h.
2021-05-08 20:35:39 +02:00
Willy Tarreau
e08f4bf27f MINOR: task: stop including stream.h from task.c
This one comes with a very deep dependency hell, only to know that
process_stream() is a function. Dropping it reduces the preprocessed
output from 1.5MB to 640kB.
2021-05-08 20:27:08 +02:00
Willy Tarreau
c79e89853b BUILD: task: remove unused includes from task.c
freq_ctr.h and time.h are not used, let's drop them.
2021-05-08 20:27:08 +02:00
Willy Tarreau
08138612a4 REORG: config: uninline warnifnotcap() and failifnotcap()
These ones are used by virtually every config parser. Not only they
provide no benefit in being inlined, but they imply a very deep
dependency starting at proxy.h, which results for example in task.c
including openssl.

Let's move these two functions to cfgparse.c.
2021-05-08 20:27:08 +02:00
Willy Tarreau
3b63ca20f4 REORG: stick-table: uninline stktable_alloc_data_type()
This function has no business being inlined in stick_table.h since it's
only used at boot time by the config parser. In addition it causes an
undesired dependency on tools.h because it uses parse_time_err(). Let's
move it to stick_table.c.
2021-05-08 20:24:09 +02:00
Willy Tarreau
e59b5169b3 BUILD: connection: move list_mux_proto() to connection.c
No idea why this was put inlined into connection.h, it's used only once
for haproxy -vv, and requires tools.h, causing an undesired dependency
from connection.h. Let's move it to connection.c instead where it ought
to have been.
2021-05-08 20:24:09 +02:00
Willy Tarreau
03f839d0ea BUILD: fcgi-app: include proxy.h in fcgi-app.c
It's needed for proxies_list and used to be inherited via cfgparse.h.
2021-05-08 20:24:09 +02:00
Willy Tarreau
daa6f1a33d BUILD: filters: include proxy.h in filters.c
It's needed for proxies_list and used to be inherited via cfgparse.h.
2021-05-08 20:24:09 +02:00
Willy Tarreau
7c6685770d BUILD: mworker: include proxy.h in mworker.c
It's needed for proxies_list and used to be inherited via cfgparse.h.
2021-05-08 20:24:09 +02:00
Willy Tarreau
817538e397 BUILD: sink: include proxy.h in sink.c
It's needed for proxies_list but was missing.
2021-05-08 20:24:09 +02:00
Willy Tarreau
b00a8e30f1 BUILD: server: include missing proxy.h in server.c
It's needed for a number of functions and definitions but was missing.
2021-05-08 20:24:09 +02:00
Willy Tarreau
ba6300ea62 BUILD: server: include tools.h from server.c
A lot of functions from tools.h are used there but the file was only
inherited via other ones.
2021-05-08 19:37:41 +02:00
Willy Tarreau
ce65cbec38 BUILD: udp: include tools.h from proto_udp.c
A few functions are used from there for address conversion but the
file wasn't included.
2021-05-08 13:59:56 +02:00
Willy Tarreau
c1a689f2eb BUILD: queue: include tools.h from queue.c
It uses memprintf() without including the file because it inherited
it from other ones.
2021-05-08 13:59:05 +02:00
Willy Tarreau
745e98ce79 BUILD: mworker: include tools.h from mworker.c
It needs it for memprintf() but didn't include the file.
2021-05-08 13:58:19 +02:00
Willy Tarreau
c624da06c6 BUILD: compression: include tools.h in compression.c
It needs it for memprintf() but it wasn't included.
2021-05-08 13:57:19 +02:00
Willy Tarreau
67046bfc50 BUILD: vars: include tools.h in vars.c
A number of functions from tools.h are used there but the file was not
included.
2021-05-08 13:56:31 +02:00
Willy Tarreau
485261beab BUILD: payload: include tools.h in payload.c
It needs it for memprintf() but used to inherit it via other include files.
2021-05-08 13:55:40 +02:00
Willy Tarreau
9f9e9fc20c BUILD: dns: include tools.h in dns.c
It is used for get_addr_len() without being included. It could be worth
splitting address manipulation functions to a different set of files.
2021-05-08 13:09:46 +02:00
Willy Tarreau
bf1ae1a4b1 BUILD: server-state: include tools.h from server_state.c
Many functions from tools.h are called there without the file being
included.
2021-05-08 13:08:34 +02:00
Willy Tarreau
908908ef2a BUILD: connection: include tools.h in connection.c
Several functions from tools.h are called there without the file being
included.
2021-05-08 13:07:31 +02:00
Willy Tarreau
4bad5e2080 BUILD: sink: include tools.h in sink.c
Several functions from tools.h are used in sink.c without tools.h being
included.
2021-05-08 13:05:30 +02:00
Willy Tarreau
ce6700aec5 BUILD: cache: include tools.h in cache.c
cache.c uses a lot of functions from tools.h without including it.
2021-05-08 13:03:55 +02:00
Willy Tarreau
523ca9d102 BUILD: session: include tools.h in session.c
The file session.c calls plenty of functions from tools.h but did not
include it.
2021-05-08 13:03:04 +02:00
Willy Tarreau
e684483ec5 BUILD: proxy: include tools.h in proxy.c
Many functions are used from tools.h but the file wasn't included and
was inherited through others.
2021-05-08 13:02:07 +02:00
Willy Tarreau
4cbf62d48a BUILD: htx: include tools.h in http_htx.c
Several functions from tools.h are called there and it used to be
inherited through others.
2021-05-08 13:01:23 +02:00
Willy Tarreau
e9dcb3cd8a BUILD: config: include tools.h in cfgparse-listen.c
Many functions defined in tools.h were called there but the file used
to be inherited via others.
2021-05-08 13:00:23 +02:00
Willy Tarreau
ca14dd5537 BUILD: resolvers: include tools.h
Many functions from tools.h are called there but it was inherited via others.
2021-05-08 12:59:47 +02:00
Willy Tarreau
e16ada16d9 BUILD: spoe: flt_spoe.c needs tools.h
It uses many functions declared there but used to inherit it through others.
2021-05-08 12:57:17 +02:00
Willy Tarreau
cc81ecac44 BUILD: config: cfgparse-ssl.c needs tools.h
It calls parse_time_err() which is defined there but used to inherit it
through others.
2021-05-08 12:54:42 +02:00
Willy Tarreau
cb72b7e028 BUILD: ssl: ssl_utils requires chunk.h
It uses chunk_printf() so it needs it. Currently it gets it through
others.
2021-05-08 12:52:56 +02:00
Willy Tarreau
15f9ac3c59 REORG: mworker: move proc_self from global to mworker
Only mworker uses proc_self, and it was declared in global.h, forcing
users of global.h to include mworker and its dependencies.

Moving it to mworker reduces the preprocessed size of version.c from
170 to 125kB by shrinking the number of local includes from 30 to 16
and the number of system includes from 147 to 132.
2021-05-08 12:34:44 +02:00
Willy Tarreau
e8ceea1345 BUILD: auth: include missing list.h
list_for_each_entry() requires list.h but used to inherit it by accident
through global.h and mworker-t.h. Let's explicitly add it.
2021-05-08 12:29:51 +02:00
Willy Tarreau
7f673c2cde BUILD: wdt: include signal-t.h
WDT_SIG is used there, thus signal-t.h is required. Currently it's
retrieved by accident through global.h.
2021-05-08 12:29:01 +02:00
Willy Tarreau
cfc4f24d80 REORG: vars: move the "proc" scope variables out of the global struct
The presence of this field causes a long dependency chain because almost
everyone includes global-t.h, and vars include sample_data which include
some system includes as well as HTTP parts.

There is absolutely no reason for having the process-wide variables in
the global struct, let's just move them into vars.c and vars.h. This
reduces from ~190k to ~170k the preprocessed output of version.c.
2021-05-08 12:11:29 +02:00
Willy Tarreau
9eec7e206e MINOR: config: mark tune.fd.edge-triggered as experimental
This one is stated as experimental in the doc but could still be used
by accidental copy-paste. Let's mark it with KWF_EXPERIMENTAL so that
users have to opt-in to use it.
2021-05-08 11:06:32 +02:00
Willy Tarreau
c5977728b3 MINOR: stats: make "show info" able to report rates as floats when asked
Now "show info float" will also report SSL rates, connection rates and
key reuse ratios as floats. This can be convenient at very low rates.

Note that the SSL reuse ratio which used to commonly oscillate between
0 and 1 under load is now more often above zero with small values. It
indicates that for better stability we shouldn't be comparing a key rate
with a connection rate but instead we should measure the reuse rate at
its source.
2021-05-08 10:52:12 +02:00
Willy Tarreau
e8abc3293f MINOR: stats: report uptime and start time as floats with subsecond resolution
When "show info float" is used, the uptime and start time will be reported
with subsecond resolution (microsecond actually since timeval is used).
2021-05-08 10:52:12 +02:00
Willy Tarreau
d37e26eaa6 MINOR: stats: use tv_remain() to precisely compute the uptime
We'll have to support reporting sub-second uptimes, so let's use the
appropriate function which will automatically adjust the tv_usec field.
In addition to this, it will also report a more accurate uptime thanks
to considering the sub-second part in the result.
2021-05-08 10:52:12 +02:00
Willy Tarreau
2745620240 MINOR: stats: support an optional "float" option to "show info"
This will allow some fields to be produced with a higher accuracy when
the requester indicates being able to parse floats. Rates and times are
among the elements which can make sense.
2021-05-08 10:52:12 +02:00
Willy Tarreau
0b26b3866c MINOR: stats: pass the appctx flags to stats_fill_info()
Currently the stats filling function knows nothing about the caller's
needs, so let's pass the STAT_* flags so that it can adapt to the
requester's constraints.
2021-05-08 10:52:12 +02:00
Willy Tarreau
6004fb7681 MINOR: stats: add the HTML conversion for float types
For the prometheus exporter, a new float type was added for the fields
and its conversion was added everywhere except for the HTML output.
Now that we have F2H() we can implement it for consistency.
2021-05-08 10:48:17 +02:00
Willy Tarreau
065ba3186e MINOR: stats: avoid excessive padding of float values with trailing zeroes
When emitting stats, we don't need to have 6 zeroes after the decimal point
for each value, so let's trim floating point numbers to the longest needed
only.
2021-05-08 10:48:17 +02:00
Willy Tarreau
ae03d26eea MINOR: tools: add a float-to-ascii conversion function
We already had ultoa_r() and friends but nothing to emit inline floats.
This is now done with ftoa_r() and F2A/F2H. Note that the latter both use
the itoa_str[] as temporary storage and that the HTML format currently is
the exact same as the ASCII one. The trailing zeroes are always timmed so
these outputs are usable in user-visible output.
2021-05-08 10:48:17 +02:00
Willy Tarreau
56d1d8dab0 MINOR: tools: implement trimming of floating point numbers
When using "%f" to print a float, it automatically gets 6 digits after
the decimal point and there's no way to automatically adjust to the
required ones by dropping trailing zeroes. This function does exactly
this and automatically drops the decimal point if all digits after it
were zeroes. This will make numbers more friendly in stats and makes
outputs shorter (e.g. JSON where everything is just a "number").

The function is designed to be easy to use with snprint() and chunks:

  snprintf:
    flt_trim(buf, 0, snprintf(buf, sizeof(buf), "%f", x));

  chunk_printf:
    out->data = flt_trim(out->area, 0, chunk_printf(out, "%f", x));

  chunk_appendf:
    size_t prev_data = out->data;
    out->data = flt_trim(out->area, prev_data, chunk_appendf(out, "%f", x));
2021-05-08 10:42:11 +02:00
Willy Tarreau
a1169b6231 MINOR: sample: improve error reporting on missing arg to strcmp() converter
Calling the strcmp() converter with no argument yields this strange error:

  [ALERT]    (31439) : parsing [test.cfg:3] : error detected in frontend 'f' while parsing 'http-request redirect' rule : failed to parse sample expression <src,strcmp]> : invalid args in converter 'strcmp' : failed to register variable name ''.

This is because the vars name check tries to see if it can create such a
variable having an empty name. Let's at least make a special case of the
missing argument. Now we can read a more explicit:

  [ALERT]    (31655) : parsing [test.cfg:3] : error detected in frontend 'f' while parsing 'http-request redirect' rule : failed to parse sample expression <src,strcmp]> : invalid args in converter 'strcmp' : missing variable name.

This was done for secure_strcmp() as well.
2021-05-08 06:55:25 +02:00
Amaury Denoyelle
24abb0cdc1 BUG/MINOR: server: do not report diag for peer servers with null weight
Only check servers attached to a proxy with PR_CAP_LB.

This does not need to be backported as the diag message was added in the
current 2.4-dev branch.
2021-05-07 15:20:54 +02:00
Amaury Denoyelle
b979f59871 MINOR: proxy: define PR_CAP_LB
Add a new proxy capability for proxy with load-balancing capabilities.
This help to differentiate listen/frontend/backend with special proxies
such as peer proxies.
2021-05-07 15:12:20 +02:00
Amaury Denoyelle
86c1d0fddb BUILD: fix usage of ha_alert without format string
The compilation is failing due to no format string used in ha_alert.
This does not need to be backported.
2021-05-07 15:07:21 +02:00
Amaury Denoyelle
a9e639afe2 MINOR: http_act: mark normalize-uri as experimental
normalize-uri http rule is marked as experimental, so it cannot be
activated without the global 'expose-experimental-directives'. The
associated vtc is updated to be able to use it.
2021-05-07 14:35:02 +02:00
Amaury Denoyelle
5dfdf3e5b0 MINOR: stats: report tainted on show info
Add a new info field ST_F_TAINTED to dump tainted status at the end of
the 'show info' output.
2021-05-07 14:35:02 +02:00
Amaury Denoyelle
f492992065 MINOR: cli: set tainted when using CLI expert/experimental mode
Mark the process as tainted as soon as a command command only accessible
in expert or experimental mode is executed.
2021-05-07 14:35:02 +02:00
Amaury Denoyelle
0351773534 MINOR: action: implement experimental actions
Support experimental actions. It is mandatory to use
'expose-experimental-directives' before to be able to use them.

If such action is present in the config file, the tainted status of the
process is updated. Another tainted status is set when an experimental
action is executed.
2021-05-07 14:35:02 +02:00
Amaury Denoyelle
e4a617c931 MINOR: action: replace match_pfx by a keyword flags field
Define a new keyword flag KWF_MATCH_PREFIX. This is used to replace the
match_pfx field of action struct.

This has the benefit to have more explicit action declaration, and now
it is possible to quickly implement experimental actions.
2021-05-07 14:35:01 +02:00
Amaury Denoyelle
d2e53cd47e MINOR: cfgparse: implement experimental config keywords
Add a new flag to mark a keyword as experimental. An experimental
keyword cannot be used if the global 'expose-experimental-directives' is
not present first.

Only keywords parsed through a standard cfg_keywords lists in
global/proxies section will be automatically detected if declared
experimental. To support a keyword outside of these lists,
check_kw_experimental must be called manually during its parsing.

If an experimental keyword is present in the config, the tainted flag is
updated.

For the moment, no keyword is marked as experimental.
2021-05-07 14:34:41 +02:00