Commit Graph

12588 Commits

Author SHA1 Message Date
Willy Tarreau
9f3129e583 MEDIUM: pools: move the cache into the pool header
Initially per-thread pool caches were stored into a fixed-size array.
But this was a bit ugly because the last allocated pools were not able
to benefit from the cache at all. As a work around to preserve
performance, a size of 64 cacheable pools was set by default (there
are 51 pools at the moment, excluding any addon and debugging code),
so all in-tree pools were covered, at the expense of higher memory
usage.

In addition an index had to be calculated for each pool, and was used
to acces the pool cache head into that array. The pool index was not
even stored into the pools so it was required to determine it to access
the cache when the pool was already known.

This patch changes this by moving the pool cache head into the pool
head itself. This way it is certain that each pool will have its own
cache. This removes the need for index calculation.

The pool cache head is 32 bytes long so it was aligned to 64B to avoid
false sharing between threads. The extra cost is not huge (~2kB more
per pool than before), and we'll make better use of that space soon.
The pool cache head contains the size, which should probably be removed
since it's already in the pool's head.
2021-04-19 15:24:33 +02:00
Willy Tarreau
3e970b11eb MINOR: pools: drop the unused static history of artificially failed allocs
When building with DEBUG_FAIL_ALLOC we call a random generator to decide
whether the pool alloc should succeed or fail, and there was a preliminary
debugging mechanism to keep sort of a history of the previous decisions. But
it was never used, enforces a lock during the allocation, and forces to use
static variables, all of which are limiting the ability to pursue the pools
cleanups with no real benefit. Let's get rid of them now.
2021-04-19 15:24:33 +02:00
Willy Tarreau
a5b229d01d BUG/MINOR: pools/buffers: make sure to always reserve the required buffers
Since recent commit ae07592 ("MEDIUM: pools: add CONFIG_HAP_NO_GLOBAL_POOLS
and CONFIG_HAP_GLOBAL_POOLS") the pre-allocation of all desired reserved
buffers was not done anymore on systems not using the shared cache. This
basically has no practical impact since these ones will quickly be refilled
by all the ones used at run time, but it may confuse someone checking if
they're allocated in "show pools".

That's only 2.4-dev, no backport is needed.
2021-04-19 15:24:33 +02:00
Willy Tarreau
932dd19cc3 BUG/MINOR: pools: maintain consistent ->allocated count on alloc failures
When running with CONFIG_HAP_NO_GLOBAL_POOLS, it's theoritically possible
to keep an incorrect count of allocated entries in a pool because the
allocated counter was used as a cumulated counter of alloc calls instead
of a number of currently allocated items (it's possible the meaning has
changed over time). The only impact in this mode essentially is that
"show pools" will report incorrect values. But this would only happen on
limited pools, which is not even certain still exist.

This was added by recent commit 0bae07592 ("MEDIUM: pools: add
CONFIG_HAP_NO_GLOBAL_POOLS and CONFIG_HAP_GLOBAL_POOLS") so no backport
is needed.
2021-04-19 15:24:33 +02:00
Tim Duesterhus
5be6ab269e MEDIUM: http_act: Rename uri-normalizers
This patch renames all existing uri-normalizers into a more consistent naming
scheme:

1. The part of the URI that is being touched.
2. The modification being performed as an explicit verb.
2021-04-19 09:05:57 +02:00
Tim Duesterhus
a407193376 MINOR: uri_normalizer: Add a percent-upper normalizer
This normalizer uppercases the hexadecimal characters used in percent-encoding.

See GitHub Issue #714.
2021-04-19 09:05:57 +02:00
Tim Duesterhus
d7b89be30a MINOR: uri_normalizer: Add a sort-query normalizer
This normalizer sorts the `&` delimited query parameters by parameter name.

See GitHub Issue #714.
2021-04-19 09:05:57 +02:00
Tim Duesterhus
560e1a6352 MINOR: uri_normalizer: Add support for supressing leading ../ for dotdot normalizer
This adds an option to supress `../` at the start of the resulting path.
2021-04-19 09:05:57 +02:00
Tim Duesterhus
9982fc2bbd MINOR: uri_normalizer: Add a dotdot normalizer to http-request normalize-uri
This normalizer merges `../` path segments with the predecing segment, removing
both the preceding segment and the `../`.

Empty segments do not receive special treatment. The `merge-slashes` normalizer
should be executed first.

See GitHub Issue #714.
2021-04-19 09:05:57 +02:00
Tim Duesterhus
d371e99d1c MINOR: uri_normalizer: Add a merge-slashes normalizer to http-request normalize-uri
This normalizer merges adjacent slashes into a single slash, thus removing
empty path segments.

See GitHub Issue #714.
2021-04-19 09:05:57 +02:00
Tim Duesterhus
d2bedcc4ab MINOR: uri_normalizer: Add http-request normalize-uri
This patch adds the `http-request normalize-uri` action that was requested in
GitHub issue #714.

Normalizers will be added in the next patches.
2021-04-19 09:05:57 +02:00
Tim Duesterhus
dbd25c34de MINOR: uri_normalizer: Add uri_normalizer module
This is in preparation for future patches.
2021-04-19 09:05:57 +02:00
Christopher Faulet
1d26f22e05 BUG/MINOR: logs: Report the true number of retries if there was no connection
When the session is aborted before any connection attempt to any server, the
number of connection retries reported in the logs is wrong. It happens
because when the retries counter is not strictly positive, we consider the
max number of retries was reached and the backend retries value is used. It
is obviously wrong when no connectioh was performed.

In fact, at this stage, the retries counter is initialized to 0. But the
backend stream-interface is in the INI state. Once it is set to SI_ST_REQ,
the counter is set to the backend value. And it is the only possible state
transition from INI state. Thus it is safe to rely on it to fix the bug.

This patch must be backported to all stable versions.
2021-04-19 08:52:17 +02:00
Christopher Faulet
a7d6cf24fb BUG/MINOR: http_htx: Remove BUG_ON() from http_get_stline() function
The http_get_stline() was designed to be called from HTTP analyzers. Thus
before any data forwarding. To prevent any invalid usage, two BUG_ON()
statements were added. However, it is not a good idea because it is pretty
hard to be sure no HTTP sample fetch will never be called outside the
analyzers context. Especially because there is at least one possible area
where it may happens. An HTTP sample fetch may be used inside the unique-id
format string. On the normal case, it is generated in AN_REQ_HTTP_INNER
analyzer. But if an error is reported too early, the id is generated when
the log is emitted.

So, it is safer to remove the BUG_ON() statements and consider the normal
behavior is to return NULL if the first block is not a start-line. Of
course, this means all calling functions must test the return value or be
sure the start-line is really there.

This patch must be backported as far as 2.0.
2021-04-19 08:51:22 +02:00
Christopher Faulet
003df1cff9 MINOR: tcp_samples: Be able to call bc_src/bc_dst from the health-checks
The new L4 sample fetches used to get source and destination info of the
backend connection may now be called from an health-check.
2021-04-19 08:31:05 +02:00
Christopher Faulet
7d081f02a4 MINOR: tcp_samples: Add samples to get src/dst info of the backend connection
This patch adds 4 new sample fetches to get the source and the destination
info (ip address and port) of the backend connection :

 * bc_dst      : Returns the destination address of the backend connection
 * bc_dst_port : Returns the destination port of the backend connection
 * bc_src      : Returns the source address of the backend connection
 * bc_src_port : Returns the source port of the backend connection

The configuration manual was updated accordingly.
2021-04-19 08:31:05 +02:00
Christopher Faulet
6f97a611c8 BUG/MINOR: http-fetch: Make method smp safe if headers were already forwarded
When method sample fetch is called, if an exotic method is found
(HTTP_METH_OTHER), when smp_prefetch_htx() is called, we must be sure the
start-line is still there. Otherwise, HAproxy may crash because of a NULL
pointer dereference, for instance if the method sample fetch is used inside
a unique-id format string. Indeed, the unique id may be generated when the
log message is emitted. At this stage, the request channel is empty.

This patch must be backported as far as 2.0. But the bug exists in all
stable versions for the legacy HTTP mode too. Thus it must be adapted to the
legacy HTTP mode and backported to all other stable versions.
2021-04-19 08:31:05 +02:00
Christopher Faulet
4bef8d1d46 BUG/MINOR: ssl-samples: Fix ssl_bc_* samples when called from a health-check
For all ssl_bc_* sample fetches, the test on the keyword when called from a
health-check is inverted. We must be sure the 5th charater is a 'b' to
retrieve a connection.

This patch must be backported as far as 2.2.
2021-04-19 08:31:05 +02:00
Christopher Faulet
242f8ce060 MINOR: connection: Make bc_http_major compatible with tcp-checks
bc_http_major sample fetch now works when it is called from a
tcp-check. When it happens, the session origin is a check. The backend
connection is retrieved from the conn-stream attached to the check.

If required, this path may easily be backported as far as 2.2.
2021-04-19 08:31:05 +02:00
Christopher Faulet
f4dd9ae5c7 BUG/MINOR: connection: Fix fc_http_major and bc_http_major for TCP connections
fc_http_major and bc_http_major sample fetches return the major digit of the
HTTP version used, respectively, by the frontend and the backend
connections, based on the mux. However, in reality, "2" is returned if the
H2 mux is detected, otherwise "1" is inconditionally returned, regardless
the mux used. Thus, if called for a raw TCP connection, "1" is returned.

To fix this bug, we now get the multiplexer flags, if there is one, to be
sure MX_FL_HTX is set.

I guess it was made this way on purpose when the H2 multiplexer was
introduced in the 1.8 and with the legacy HTTP mode there is no other
solution at the connection level. Thus this patch should be backported as
far as 2.2. For the 2.0, it must be evaluated first because of the legacy
HTTP mode.
2021-04-19 08:24:38 +02:00
Christopher Faulet
fd81848c22 MINOR: logs: Add support of checks as session origin to format lf strings
When a log-format string is built from an health-check, the session origin
is the health-check itself and not a connection. In addition, there is no
stream. It means for now some formats are not supported: %s, %sc, %b, %bi,
%bp, %si and %sp.

Thanks to this patch, the session origin is converted to a check. So it is
possible to retrieve the backend and the backend connection. Note this
session have no listener, thus %ft format must be guarded.

This patch is light and standalone, thus it may be backported as far as 2.2
if required. However, because the error is human, it is probably better to
wait a bit to be sure everything is properly protected.
2021-04-19 08:22:15 +02:00
Christopher Faulet
0f1fc23d4e BUG/MINOR: checks: Set missing id to the dummy checks frontend
The dummy frontend used to create the session of the tcp-checks is
initialized without identifier. However, it is required because this id may
be used without any guard, for instance in log-format string via "%f" or
when fe_name sample fetch is called. Thus, an unset id may lead to crashes.

This patch must be backported as far as 2.2.
2021-04-17 11:14:58 +02:00
Christopher Faulet
76b44195c9 MINOR: threads: Only consider running threads to end a thread harmeless period
When a thread ends its harmeless period, we must only consider running
threads when testing threads_want_rdv_mask mask. To do so, we reintroduce
all_threads_mask mask in the bitwise operation (It was removed to fix a
deadlock).

Note that for now it is useless because there is no way to stop threads or
to have threads reserved for another task. But it is safer this way to avoid
bugs in the future.
2021-04-17 11:14:58 +02:00
Alex
51c8ad45ce MINOR: sample: converter: Add json_query converter
With the json_query can a JSON value be extacted from a header
or body of the request and saved to a variable.

This converter makes it possible to handle some JSON workload
to route requests to different backends.
2021-04-15 17:07:03 +02:00
Alex
41007a6835 MINOR: sample: converter: Add mjson library.
This library is required for the subsequent patch which adds
the JSON query possibility.

It is necessary to change the include statement in "src/mjson.c"
because the imported includes in haproxy are in "include/import"

orig: #include "mjson.h"
new:  #include <import/mjson.h>
2021-04-15 17:05:38 +02:00
Moemen MHEDHBI
848216f108 CLEANUP: sample: align samples list in sample.c 2021-04-13 17:28:22 +02:00
Moemen MHEDHBI
92f7d43c5d MINOR: sample: add ub64dec and ub64enc converters
ub64dec and ub64enc are the base64url equivalent of b64dec and base64
converters. base64url encoding is the "URL and Filename Safe Alphabet"
variant of base64 encoding. It is also used in in JWT (JSON Web Token)
standard.
RFC1421 mention in base64.c file is deprecated so it was replaced with
RFC4648 to which existing converters, base64/b64dec, still apply.

Example:
  HAProxy:
    http-request return content-type text/plain lf-string %[req.hdr(Authorization),word(2,.),ub64dec]
  Client:
    Token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiZm9vIiwia2V5IjoiY2hhZTZBaFhhaTZlIn0.5VsVj7mdxVvo1wP5c0dVHnr-S_khnIdFkThqvwukmdg
    $ curl -H "Authorization: Bearer ${TOKEN}" http://haproxy.local
    {"user":"foo","key":"chae6AhXai6e"}
2021-04-13 17:28:13 +02:00
Thayne McCombs
b28430591d BUG/MEDIUM: sample: Fix adjusting size in field converter
Adjust the size of the sample buffer before we change the "area"
pointer. The change in size is calculated as the difference between the
original pointer and the new start pointer. But since the
`smp->data.u.str.area` assignment results in `smp->data.u.str.area` and
`start` being the same pointer, we always ended up substracting zero.
This changes it to change the size by the actual amount it changed.

I'm not entirely sure what the impact of this is, but the previous code
seemed wrong.

[wt: from what I can see the only harmful case is when the output is
 converted to a stick-table key, it could result in zeroing past the
 end of the buffer; other cases do not touch beyond ->data]
2021-04-13 12:12:48 +02:00
Christopher Faulet
b15625a43b MINOR: cfgparse/proxy: Group alloc error handling during proxy section parsing
All allocation errors in cfg_parse_listen() are now handled in a unique
place under the "alloc_error" label. This simplify a bit error handling in
this function.
2021-04-12 22:04:19 +02:00
Christopher Faulet
b45a7d4b74 BUG/MINOR: cfgparse/proxy: Hande allocation errors during proxy section parsing
At several places during the proxy section parsing, memory allocation was
performed with no check. Result is now tested and an error is returned if
the allocation fails.

This patch may be backported to all stable version but it only fixes
allocation errors during configuration parsing. Thus, it is not mandatory.
2021-04-12 21:35:12 +02:00
Christopher Faulet
0c6d1dcf7d BUG/MINOR: listener: Handle allocation error when allocating a new bind_conf
Allocation error are now handled in bind_conf_alloc() functions. Thus
callers, when not already done, are also updated to catch NULL return value.

This patch may be backported (at least partially) to all stable
versions. However, it only fix errors durung configuration parsing. Thus it
is not mandatory.
2021-04-12 21:33:43 +02:00
Christopher Faulet
2e848a9b75 BUG/MINOR: cfgparse/proxy: Fix some leaks during proxy section parsing
Allocated variables are now released when an error occurred during
use_backend, use-server, force/ignore-parsing, stick-table, stick and stats
directives parsing. For some of these directives, allocation errors have
been added.

This patch may be backported to all stable version but it only fixes leaks
or allocation errors during configuration parsing. Thus, it is not
mandatory. It should fix issue #1119.
2021-04-12 21:33:39 +02:00
Christopher Faulet
3a9a12bb2a BUG/MINOR: hlua: Fix memory leaks on error path when registering a cli keyword
When an error occurred in hlua_register_cli(), the allocated lua function
and keyword must be released to avoid memory leaks.

This patch depends on "MINOR: hlua: Add function to release a lua
function". It may be backported in all stable versions.
2021-04-12 19:05:05 +02:00
Christopher Faulet
5c028d7f9d BUG/MINOR: hlua: Fix memory leaks on error path when registering a service
When an error occurred in hlua_register_service(), the allocated lua
function and keyword must be released to avoid memory leaks.

This patch depends on "MINOR: hlua: Add function to release a lua
function". It may be backported in all stable versions.
2021-04-12 19:04:42 +02:00
Christopher Faulet
4fc9da01d2 BUG/MINOR: hlua: Fix memory leaks on error path when registering an action
When an error occurred in hlua_register_action(), the allocated lua function
and keyword must be released to avoid memory leaks.

This patch depends on "MINOR: hlua: Add function to release a lua
function". It may be backported in all stable versions.
2021-04-12 19:04:42 +02:00
Christopher Faulet
528526f2cc BUG/MINOR: hlua: Fix memory leaks on error path when parsing a lua action
hen an error occurred in action_register_lua(), the allocated hlua rule and
arguments must be released to avoid memory leaks.

This patch may be backported in all stable versions.
2021-04-12 19:04:42 +02:00
Christopher Faulet
2567f18382 BUG/MINOR: hlua: Fix memory leaks on error path when registering a fetch
When an error occurred in hlua_register_fetches(), the allocated lua
function and keyword must be released to avoid memory leaks.

This patch depends on "MINOR: hlua: Add function to release a lua
function". It may be backported in all stable versions. It should fix #1112.
2021-04-12 19:04:42 +02:00
Christopher Faulet
aa22430bba BUG/MINOR: hlua: Fix memory leaks on error path when registering a converter
When an error occurred in hlua_register_converters(), the allocated lua
function and keyword must be released to avoid memory leaks.

This patch depends on "MINOR: hlua: Add function to release a lua
function". It may be backported in all stable versions.
2021-04-12 19:04:42 +02:00
Christopher Faulet
5294ec0708 BUG/MINOR: hlua: Fix memory leaks on error path when registering a task
When an error occurred in hlua_register_task(), the allocated lua context
and task must be released to avoid memory leaks.

This patch may be backported in all stable versions.
2021-04-12 19:04:42 +02:00
Christopher Faulet
dda44442d5 MINOR: hlua: Add function to release a lua function
release_hlua_function() must be used to release a lua function. Some fixes
depends on this function.
2021-04-12 15:46:53 +02:00
Christopher Faulet
147b8c919c MINOIR: checks/trace: Register a new trace source with its events
Add the trace support for the checks. Only tcp-check based health-checks are
supported, including the agent-check.

In traces, the first argument is always a check object. So it is easy to get
all info related to the check. The tcp-check ruleset, the conn-stream and
the connection, the server state...
2021-04-12 12:09:36 +02:00
Christopher Faulet
6d80b63e3c MINOR: trace: Add the checks as a possible trace source
To be able to add the trace support for the checks, a new kind of source
must be added for this purpose.
2021-04-12 12:09:36 +02:00
Willy Tarreau
44982715ba MEDIUM: time: make the clock offset global and no per-thread
Since 1.8 for simplicity the time offset used to compensate for time
drift and jumps had been stored per thread. But with a global time,
the complexit has significantly increased.

What this patch does in order to address this is to get back to the
origins of the pre-thread time drift correction, and keep a single
offset between the system's date and the current global date.

The thread first verifies from the before_poll date if the time jumped
backwards or forward, then either fixes it by computing the new most
likely date, or applies the current offset to this latest system date.
In the first case, if the date is out of range, the old one is reused
with the max_wait offset or not depending on the interrupted flag.
Then it compares its date to the global date and updates both so that
both remain monotonic and that the local date always reflects the
latest known global date.

In order to support atomic updates to the offset, it's saved as a
ullong which contains both the tv_sec and tv_usec parts in its high
and low words. Note that a part of the patch comes from the inlining
of the equivalent of tv_add applied to the offset to make sure that
signed ints are permitted (otherwise it depends on how timeval is
defined).

This is significantly more reliable than the previous model as the
global time should move in a much smoother way, and not according
to what thread last updated it, and the thread-local time should
always be very close to the global one.

Note that (at least for debugging) a cheap way to measure processing
lag would consist in measuring the difference between global_now_ms
and now_ms, as long as other threads keep it up-to-date.
2021-04-11 23:59:37 +02:00
Willy Tarreau
7e4a557f64 MINOR: time: change the global timeval and the the global tick at once
Instead of using two CAS loops, better compute the two units
simultaneously and update them at once. There is no guarantee that
the update will be synchronous, but we don't care, what matters is
that both are monotonically updated and that global_now_ms always
follows the last known value of global_now.
2021-04-11 23:47:54 +02:00
Willy Tarreau
70cb3026a8 MINOR: time: remove useless variable copies in tv_update_date()
In the global_now loop, we used to set tmp_adj from adjusted, then
set update it from tmp_now, then set adjusted back to tmp_adj, and
finally set now from adjusted. This is a long and unneeded set of
moves resulting from years of code changes. Let's just set now
directly in the loop, stop using adjusted and remove tmp_adj.
2021-04-11 23:47:01 +02:00
Willy Tarreau
c4c80fb4ea MINOR: time: move the time initialization out of tv_update_date()
The time initialization was made a bit complex because we rely on a
dummy negative argument to reset all fields, leaving no distinction
between process-level initialization and thread-level initialization.
This patch changes this by introducing two functions, one for the
process and the second one for the threads. This removes ambigous
test and makes sure that the relevant fields are always initialized
exactly once. This also offers a better solution to the bug fixed in
commit b48e7c001 ("BUG/MEDIUM: time: make sure to always initialize
the global tick") as there is no more special values for global_now_ms.

It's simple enough to be backported if any other time-related issues
are encountered in stable versions in the future.
2021-04-11 23:45:48 +02:00
Willy Tarreau
61c72c366e CLEANUP: time: remove the now unused ms_left_scaled
It was only used by freq_ctr and is not used anymore. In addition the
local curr_sec_ms was removed, as well as the equivalent extern
definitions which did not exist anymore either.
2021-04-11 14:01:53 +02:00
Willy Tarreau
fc6323ad82 MEDIUM: freq_ctr: replace the per-second counters with the generic ones
It remains cumbersome to preserve two versions of the freq counters and
two different internal clocks just for this. In addition, the savings
from using two different mechanisms are not that important as the only
saving is a divide that is replaced by a multiply, but now thanks to
the freq_ctr_total() unificaiton the code could also be simplified to
optimize it in case of constants.

This patch turns all non-period freq_ctr functions to static inlines
which call the period-based ones with a period of 1 second. A direct
benefit is that a single internal clock is now needed for any counter
and that they now all rely on ticks.

These 1-second counters are essentially used to report request rates
and to enforce a connection rate limitation in listeners. It was
verified that these continue to work like before.
2021-04-11 11:12:55 +02:00
Willy Tarreau
fa1258f02c MINOR: freq_ctr: unify freq_ctr and freq_ctr_period into freq_ctr
Both structures are identical except the name of the field starting
the period and its description. Let's call them all freq_ctr and the
period's start "curr_tick" which is generic.

This is only a temporary change and fields are expected to remain
the same with no code change (verified).
2021-04-11 11:11:27 +02:00
Willy Tarreau
607be24a85 MEDIUM: freq_ctr: reimplement freq_ctr_remain_period() from freq_ctr_total()
Now the function becomes an inline one and only contains a divide and
a max. The divide will automatically go away with constant periods.
2021-04-11 11:11:03 +02:00
Willy Tarreau
a7a31b2602 MEDIUM: freq_ctr: make read_freq_ctr_period() use freq_ctr_total()
This one is the easiest to implement, it just requires a call and a
divide of the result. Anti-flapping correction for low-rates was
preserved.

Now calls using a constant period will be able to use a reciprocal
multiply for the period instead of a divide.
2021-04-11 11:11:03 +02:00
Willy Tarreau
f3a9f8dc5a MINOR: freq_ctr: add a generic function to report the total value
Most of the functions designed to read a counter over a period go through
the same complex loop and only differ in the way they use the returned
values, so it was worth implementing all this into freq_ctr_total() which
returns the total number of events over a period so that the caller can
finish its operation using a divide or a remaining time calculation. As
a special case, read_freq_ctr_period() doesn't take pending events but
requires to enable an anti-flapping correction at very low frequencies.
Thus the function implements it when pend<0.

Thanks to this function it will be possible to reimplement the other ones
as inline and merge the per-second ones with the arbitrary period ones
without always adding the cost of a 64 bit divide.
2021-04-11 11:10:57 +02:00
Willy Tarreau
6eb3d37bf4 MINOR: trace: make trace sources read_mostly
The trace sources are checked at plenty of places in the code and their
contents only change when trace status changes, let's mark them read_mostly.
2021-04-10 19:29:26 +02:00
Willy Tarreau
295a89c029 MINOR: pattern: make the pat_lru_seed read_mostly
This seed is created once at boot and is used in every LRU hash when
caching results. Let's mark it read_mostly.
2021-04-10 19:27:41 +02:00
Willy Tarreau
ad6722ea3a MINOR: protocol: move __protocol_by_family to read_mostly
This one is used for each outgoing connection and never changes after
boot, move it to read_mostly.
2021-04-10 19:27:41 +02:00
Willy Tarreau
14015b8880 MINOR: server: move idle_conn_task to read_mostly
This pointer is used when adding connections to the idle list and is
never changed, let's move it to the read_mostly section.
2021-04-10 19:27:41 +02:00
Willy Tarreau
56c3b8b4e8 MINOR: threads: mark all_threads_mask as read_mostly
This variable almost never changes and is read a lot in time-critical
sections. threads_want_rdv_mask is read very often as well in
thread_harmless_end() and is almost never changed (only when someone
uses thread_isolate()). Let's move both to read_mostly.
2021-04-10 19:27:41 +02:00
Willy Tarreau
ff88270ef9 MINOR: pool: move pool declarations to read_mostly
All pool heads are accessed via a pointer and should not be shared with
highly written variables. Move them to the read_mostly section.
2021-04-10 19:27:41 +02:00
Willy Tarreau
8209c9aa18 MINOR: kqueue: move kqueue_fd to read_mostly
This one only contains the list of per-thread kqueue FDs, and is used
a lot during updates. Let's mark it read_mostly to avoid false sharing
of FDs placed at the extremities.
2021-04-10 19:27:41 +02:00
Willy Tarreau
26d212c744 MINOR: epoll: move epoll_fd to read_mostly
This one only contains the list of per-thread epoll FDs, and is used
a lot during updates. Let's mark it read_mostly to avoid false sharing
of FDs placed at the extremities.
2021-04-10 19:27:41 +02:00
Willy Tarreau
a1090a5b61 MINOR: fd: move a few read-mostly variables to their own section
Some pointer to arrays such as fdtab, fdinfo, polled_mask etc are never
written to at run time but are used a lot. fdtab accesses appear a lot in
perf top because ha_used_fds is in the same cache line and is modified
all the time. This patch moves all these read-mostly variables to the
read_mostly section when defined. This way their cache lines will be
able to remain in shared state in all CPU caches.
2021-04-10 19:27:41 +02:00
Willy Tarreau
f459640ef6 MINOR: global: declare a read_mostly section
Some variables are mostly read (mostly pointers) but they tend to be
merged with other ones in the same cache line, slowing their access down
in multi-thread setups. This patch declares an empty, aligned variable
in a section called "read_mostly". This will force a cache-line alignment
on this section so that any variable declared in it will be certain to
avoid false sharing with other ones. The section will be eliminated at
link time if not used.

A __read_mostly attribute was added to compiler.h to ease use of this
section.
2021-04-10 19:27:41 +02:00
Willy Tarreau
9057a0026e CLEANUP: pattern: make all pattern tables read-only
Interestingly, all arrays used to declare patterns were read-write while
only hard-coded. Let's mark them const so that they move from data to
rodata and don't risk to experience false sharing.
2021-04-10 17:49:41 +02:00
Christopher Faulet
e2c65ba344 BUG/MINOR: mux-pt: Fix a possible UAF because of traces in mux_pt_io_cb
In mux_pt_io_cb(), if a connection error or a shutdown is detected, the mux
is destroyed. Thus we must be careful to not use it in a trace message once
destroyed.

No backport needed. This patch should fix the issue #1220.
2021-04-10 09:02:36 +02:00
Christopher Faulet
c0ae097b95 MINOIR: mux-pt/trace: Register a new trace source with its events
As for the other muxes, traces are now supported in the pt mux. All parts of
the multiplexer is covered by these traces. Events are splitted by
categories (connection, stream, rx and tx).

In traces, the first argument is always a connection. So it is easy to get
the mux context (conn->ctx). The second argument is always a conn-stream and
mau be NUUL. The third one is a buffer and it may also be NULL. Depending on
the context it is the request or the response. In all cases it is owned by a
channel. Finally, the fourth argument is an integer value. Its meaning
depends on the calling context.
2021-04-09 17:46:58 +02:00
Tim Duesterhus
403fd722ac CLEANUP: Remove useless malloc() casts
This is not C++.
2021-04-08 20:11:58 +02:00
Tim Duesterhus
b8ee894b66 CLEANUP: htx: Make http_get_stline take a const struct
Nothing is being modified there, so this can be `const`.
2021-04-08 19:40:59 +02:00
Emeric Brun
c8f3e45c6a MEDIUM: resolvers: add support of tcp address on nameserver line.
This patch re-works configuration parsing, it removes the "server"
lines from "resolvers" sections introduced in commit 56fc5d9eb:
MEDIUM: resolvers: add supports of TCP nameservers in resolvers.

It also extends the nameserver lines to support stream server
addresses such as:

resolvers
  nameserver localhost tcp@127.0.0.1:53

Doing so, a part of nameserver's init code was factorized in
function 'parse_resolvers' and removed from 'post_parse_resolvers'.
2021-04-08 14:20:40 +02:00
Willy Tarreau
4781b1521a CLEANUP: atomic/tree-wide: replace single increments/decrements with inc/dec
This patch replaces roughly all occurrences of an HA_ATOMIC_ADD(&foo, 1)
or HA_ATOMIC_SUB(&foo, 1) with the equivalent HA_ATOMIC_INC(&foo) and
HA_ATOMIC_DEC(&foo) respectively. These are 507 changes over 45 files.
2021-04-07 18:18:37 +02:00
Willy Tarreau
185157201c CLEANUP: atomic: add a fetch-and-xxx variant for common operations
The fetch_and_xxx variant is often missing for add/sub/and/or. In fact
it was only provided for ADD under the name XADD which corresponds to
the x86 instruction name. But for destructive operations like AND and
OR it's missing even more as it's not possible to know the value before
modifying it.

This patch explicitly adds HA_ATOMIC_FETCH_{OR,AND,ADD,SUB} which
cover these standard operations, and renames XADD to FETCH_ADD (there
were only 6 call places).

In the future, backport of fixes involving such operations could simply
remap FETCH_ADD(x) to XADD(x), FETCH_SUB(x) to XADD(-x), and for the
OR/AND if needed, these could possibly be done using BTS/BTR.

It's worth noting that xchg could have been renamed to fetch_and_store()
but xchg already has well understood semantics and it wasn't needed to
go further.
2021-04-07 18:18:37 +02:00
Willy Tarreau
1db427399c CLEANUP: atomic: add an explicit _FETCH variant for add/sub/and/or
Currently our atomic ops return a value but it's never known whether
the fetch is done before or after the operation, which causes some
confusion each time the value is desired. Let's create an explicit
variant of these operations suffixed with _FETCH to explicitly mention
that the fetch occurs after the operation, and make use of it at the
few call places.
2021-04-07 18:18:37 +02:00
Willy Tarreau
184b21259b MINOR: cli/show-fd: slightly reorganize the FD status flags
Slightly reorder the status flags to better match their order in the
"state" field, and also decode the "shut" state which is particularly
useful and already part of this field.
2021-04-07 18:18:37 +02:00
Willy Tarreau
1673c4a883 MINOR: fd: implement an exclusive syscall bit to remove the ugly "log" lock
There is a function called fd_write_frag_line() that's essentially used
by loggers and that is used to write an atomic message line over a file
descriptor using writev(). However a lock is required around the writev()
call to prevent messages from multiple threads from being interleaved.
Till now a SPIN_TRYLOCK was used on a dedicated lock that was common to
all FDs. This is quite not pretty as if there are multiple output pipes
to collect logs, there will be quite some contention. Now that there
are empty flags left in the FD state and that we can finally use atomic
ops on them, let's add a flag to indicate the FD is locked for exclusive
access by a syscall. At least the locking will now be on an FD basis and
not the whole process, so we can remove the log_lock.
2021-04-07 18:18:37 +02:00
Willy Tarreau
9063a660cc MINOR: fd: move .exported into fdtab[].state
No need to keep this flag apart any more, let's merge it into the global
state.
2021-04-07 18:10:36 +02:00
Willy Tarreau
5362bc9044 MINOR: fd: move .et_possible into fdtab[].state
No need to keep this flag apart any more, let's merge it into the global
state.
2021-04-07 18:09:43 +02:00
Willy Tarreau
0cc612818d MINOR: fd: move .initialized into fdtab[].state
No need to keep this flag apart any more, let's merge it into the global
state. The bit was not cleared in fd_insert() because the only user is
the function used to create and atomically send a log message to a pipe
FD, which never registers the fd. Here we clear it nevertheless for the
sake of clarity.

Note that with an extra cleaning pass we could have a bit number
here and simply use a BTS to test and set it.
2021-04-07 18:09:08 +02:00
Willy Tarreau
030dae13a0 MINOR: fd: move .cloned into fdtab[].state
No need to keep this flag apart any more, let's merge it into the global
state.
2021-04-07 18:08:29 +02:00
Willy Tarreau
b41a6e9101 MINOR: fd: move .linger_risk into fdtab[].state
No need to keep this flag apart any more, let's merge it into the global
state. The CLI's output state was extended to 6 digits and the linger/cloned
flags moved inside the parenthesis.
2021-04-07 18:07:49 +02:00
Willy Tarreau
f509065191 MEDIUM: fd: merge fdtab[].ev and state for FD_EV_* and FD_POLL_* into state
For a long time we've had fdtab[].ev and fdtab[].state which contain two
arbitrary sets of information, one is mostly the configuration plus some
shutdown reports and the other one is the latest polling status report
which also contains some sticky error and shutdown reports.

These ones used to be stored into distinct chars, complicating certain
operations and not even allowing to clearly see concurrent accesses (e.g.
fd_delete_orphan() would set the state to zero while fd_insert() would
only set the event to zero).

This patch creates a single uint with the two sets in it, still delimited
at the byte level for better readability. The original FD_EV_* values
remained at the lowest bit levels as they are also known by their bit
value. The next step will consist in merging the remaining bits into it.

The whole bits are now cleared both in fd_insert() and _fd_delete_orphan()
because after a complete check, it is certain that in both cases these
functions are the only ones touching these areas. Indeed, for
_fd_delete_orphan(), the thread_mask has already been zeroed before a
poller can call fd_update_event() which would touch the state, so it
is certain that _fd_delete_orphan() is alone. Regarding fd_insert(),
only one thread will get an FD at any moment, and it as this FD has
already been released by _fd_delete_orphan() by definition it is certain
that previous users have definitely stopped touching it.

Strictly speaking there's no need for clearing the state again in
fd_insert() but it's cheap and will remove some doubts during some
troubleshooting sessions.
2021-04-07 18:04:39 +02:00
Willy Tarreau
8d27c203ed MEDIUM: fd: prepare FD_POLL_* to move to bits 8-15
In preparation of merging FD_POLL* and FD_EV*, this only changes the
value of FD_POLL_* to use bits 8-15 (the second byte). The size of the
field has been temporarily extended to 32 bits already, as well as
the temporary variables that carry the new composite value inside
fd_update_events(). The resulting fdtab entry becomes temporarily
unaligned. All places making access to .ev or FD_POLL_* were carefully
inspected to make sure they were safe regarding this change. Only one
temporary update was needed for the "show fd" code. The code was only
slightly inflated at this step.
2021-04-07 15:08:40 +02:00
Emeric Brun
26754901e9 BUG/MEDIUM: log: fix config parse error logging on stdout/stderr or any raw fd
The regression was introduced by commit previous commit 94aab06:
MEDIUM: log: support tcp or stream addresses on log lines.

This previous patch tries to retrieve the used protocol parsing
the address using the str2sa_range function but forgets that
the raw file descriptor adresses don't specify a protocol
and str2sa_range probes an error.

This patch re-work the str2sa_range function to stop
probing error if an authorized RAW_FD address is parsed
whereas the caller request also a protocol.

It also modify the code of parse_logsrv to switch on stream
logservers only if a protocol was detected.
2021-04-07 15:01:00 +02:00
Emeric Brun
94aab06e24 MEDIUM: log: support tcp or stream addresses on log lines.
An explicit stream address prefix such as "tcp6@" "tcp4@"
"stream+ipv6@" "stream+ipv4@" or "stream+unix@" will
allocate an implicit ring buffer with a forward server
targeting the given address.

This is usefull to simply send logs to a log server in tcp
and It doesn't need to declare a ring section in configuration.
2021-04-07 09:18:34 +02:00
Emeric Brun
9533a70381 MINOR: log: register config file and line number on log servers.
This patch registers the parsed file and the line where a log server
is declared to make those information available in configuration
post check.

Those new informations were added on error messages probed resolving
ring names on post configuration check.
2021-04-07 09:18:34 +02:00
Emeric Brun
ce325c4360 MINOR: server/bind: add support of new prefixes for addresses.
Since the internal function str2sa_range is used to addresses
for different objects ('server', 'bind' but also 'log' or
'nameserver') we notice that some combinations are missing.

"ip@" is introduced to authorize the prefix "dgram+ip@" or
"stream+ip@" which dectects automatically IP version but
specify dgram or stream.

"tcp@" was introduced and is an alias for "stream+ip@".
"tcp6" and "tcp4" are now aliases for "stream+ipv6@" and
"stream+ipv4@".

"uxst@" and "uxdg@" are now aliases for "stream+unix@" and
"dgram+unix@".

This patch also adds a complete section in documentation to
describe adresses and their prefixes.
2021-04-07 09:18:32 +02:00
Thayne McCombs
a68380524b BUG/MINOR: tools: fix parsing "us" unit for timers
Commit c20ad0d8db (BUG/MINOR: tools:  make
parse_time_err() more strict on the timer validity) broke parsing the "us"
unit in timers. It caused `parse_time_err()` to return the string "s",
which indicates an error.

Now if the "u" is followed by an "s" we properly continue processing the
time instead of immediately failing.

This fixes #1209. It must be backported to all stable versions.
2021-04-06 07:31:51 +02:00
Christopher Faulet
eccb31c939 BUG/MINOR: hlua: Detect end of request when reading data for an HTTP applet
When a script retrieves request data from an HTTP applet, line per line or
not, we must be sure to properly detect the end of the request by checking
HTX_FL_EOM flag when everything was consumed. Otherwise, the script may
hang.

It is pretty easy to reproduce the bug by calling applet:receive() without
specifying any length. If the request is not chunked, the function never
returns.

The bug was introduced when the EOM block was removed. Thus, it is specific
to the 2.4. This patch should fix the issue #1207. No backport needed.
2021-04-06 07:31:51 +02:00
Christopher Faulet
8043e831d1 MINOR: acl: Add HTTP_2.0 predefined macro
HTTP_2.0 predefined macro returns true for HTTP/2 requests. HTTP/2 doen't
convey a version information, so this macro may seem a bit strange. But for
compatiblity reasons, internally, the "HTTP/2.0" version is set. Thus, it is
handy to rely on it to differenciate HTTP/1 and HTTP/2 requests.
2021-04-06 07:31:51 +02:00
Christopher Faulet
779184e35e MINOR: No longer rely on deprecated sample fetches for predefined ACLs
Some predefined ACLs were still based on deprecated sample fetches, like
req_proto_http or req_ver. Now, they use non-deprecated sample fetches. In
addition, the usage lines in the configuration manual have been updated to
be more explicit.
2021-04-05 17:21:05 +02:00
Willy Tarreau
57610c694e CONTRIB: move src/wurfl.c and contrib/wurfl to addons/wurfl
Both the source file and the dummy library are now at the same place.
Maybe the build howto could be moved there as well to make things even
cleaner.

The Makefile, MAINTAINERS, doc, and vtest matrix were updated.
2021-04-02 17:48:42 +02:00
Willy Tarreau
f8d9ec57f0 CONTRIB: move src/da.c and contrib/deviceatlas to addons/deviceatlas
Both the source file and the dummy library are now at the same place.
Maybe the build howto could be moved there as well to make things even
cleaner.

The Makefile, MAINTAINERS, doc, github build matrix, coverity checks
and travis CI's build were updated.
2021-04-02 17:48:42 +02:00
Willy Tarreau
977209d1d8 CONTRIB: move 51Degrees to addons/51degrees
Now it's much cleaner, both 51d.c and the dummy library live together and
are easier to spot and maintain. The build howto probably ought to be moved
there as well. Makefile, docs and MAINTAINERS were updated, as well as
the github CI's build matrix, travis CI's, and coverity checks.
2021-04-02 17:48:42 +02:00
Willy Tarreau
074ebcde29 CONTRIB: move some dev-specific tools to dev/
The following directories were moved from contrib/ to dev/ to make their
use case a bit clearer. In short, only developers are expected to ever
go there. The makefile was updated to build and clean from these ones.

base64/  flags/  hpack/  plug_qdisc/  poll/  tcploop/  trace/
2021-04-02 17:48:42 +02:00
Amaury Denoyelle
728be0f437 MINOR: config: diag if global section after non-global
Detect if a global section is present after another section and reports
a diagnostic about it.
2021-04-01 18:03:37 +02:00
Amaury Denoyelle
de2fab55aa MINOR: diag: diag if servers use the same cookie value
Add a diagnostic to check that two servers of the same backend does not
use the same cookie value. Ignore backup servers as it is quite common
for them to share a cookie value with a primary one.
2021-04-01 18:03:37 +02:00
Amaury Denoyelle
5a6926dcf0 MINOR: diag: create cfgdiag module
This module is intended to serve as a placeholder for various
diagnostics executed after the configuration file has been fully loaded.
2021-04-01 18:03:37 +02:00
Amaury Denoyelle
da0e7f61e0 MINOR: server: diag for 0 weight server
Output a diagnostic report if a server has been configured with a null
weight.
2021-04-01 18:03:37 +02:00
Amaury Denoyelle
c4d47d609a MINOR: cfgparse: diag for multiple nbthread statements
Output a diagnostic report if the nbthread statement is defined on
several places in the configuration.
2021-04-01 18:03:37 +02:00
Amaury Denoyelle
7b01a8dbdd MINOR: global: define diagnostic mode of execution
Define MODE_DIAG which is used to run haproxy in diagnostic mode. This
mode is used to output extra warnings about possible configuration
blunder or sub-optimal usage. It can be activated with argument '-dD'.

A new output function ha_diag_warning is implemented reserved for
diagnostic output. It serves to standardize the format of diagnostic
messages.

A macro HA_DIAG_WARN_COND is also available to automatically check if
diagnostic mode is on before executing the diagnostic check.
2021-04-01 18:03:37 +02:00
Willy Tarreau
374edc70ba CLEANUP: vars: always pre-initialize smp in vars_parse_cli_get_var()
In issue #1200 Coverity believes we may use an uninitialized field
smp.sess here while it's not possible because the returned variable
necessarily matches SCOPE_PROC hence smp.sess is not used. But it
cannot see this and it could be confusing if the code later evolved
into something more complex. That's not a critical path so let's
first reset the sample.
2021-04-01 17:04:17 +02:00
Christopher Faulet
09f88364b7 BUG/MINOR: http-fetch: Fix test on message state to capture the version
A bug was introduced when the legacy HTTP mode was removed. To capture the
HTTP version of the request or the response, we rely on the message state to
be sure the status line was received. However, the test is inverted. The
version can be captured if message headers were received, not the opposite.

This patch must be backported as far as 2.2.
2021-04-01 16:45:40 +02:00
Christopher Faulet
021a8e4d7b MEDIUM: http-rules: Add wait-for-body action on request and response side
Historically, an option was added to wait for the request payload (option
http-buffer-request). This option has 2 drawbacks. First, it is an ON/OFF
option for the whole proxy. It cannot be enabled on demand depending on the
message. Then, as its name suggests, it only works on the request side. The
only option to wait for the response payload was to write a dedicated
filter. While it is an acceptable solution for complex applications, it is a
bit overkill to simply match strings in the body.

To make everyone happy, this patch adds a dedicated HTTP action to wait for
the message payload, for the request or the response depending it is used in
an http-request or an http-response ruleset. The time to wait is
configurable and, optionally, the minimum payload size to have before stop
to wait.

Both the http action and the old http analyzer rely on the same internal
function.
2021-04-01 16:27:40 +02:00
Christopher Faulet
581db2b829 MINOR: payload/config: Warn if a L6 sample fetch is used from an HTTP proxy
L6 sample fetches are now ignored when called from an HTTP proxy. Thus, a
warning is emitted during the startup if such usage is detected. It is true
for most ACLs and for log-format strings. Unfortunately, it is a bit painful
to do so for sample expressions.

This patch relies on the commit "MINOR: action: Use a generic function to
check validity of an action rule list".
2021-04-01 15:34:22 +02:00
Christopher Faulet
42c6cf9501 MINOR: action: Use a generic function to check validity of an action rule list
The check_action_rules() function is now used to check the validity of an
action rule list. It is used from check_config_validity() function to check
L5/6/7 rulesets.
2021-04-01 15:34:22 +02:00
Christopher Faulet
2e96194d00 MINOR: htx: Make internal.strm.is_htx an internal sample fetch
It is not really a context-less sample fetch, but it is internal. And it
only fails if no stream is attached to the sample. This way, it is still
possible to use it on an HTTP proxy (L6 sample fetches are ignored now for
HTTP proxies).

If the commit "BUG/MINOR: payload/htx: Ingore L6 sample fetches for HTX
streams/checks" is backported, it may be a good idea to backport this one
too. But only as far as 2.2.
2021-04-01 15:34:22 +02:00
Christopher Faulet
a434a00864 BUG/MINOR: payload/htx: Ingore L6 sample fetches for HTX streams/checks
Use a L6 sample fetch on an HTX streams or a HTX health-check is meaningless
because data are not raw but structured. So now, these sample fetches fail
when called from an HTTP proxy. In addition, a warning has been added in the
configuration manual, at the begining of the L6 sample fetches section.

Note that req.len and res.len samples return the HTX data size instead of
failing. It is not accurate because it does not reflect the buffer size nor
the raw data length. But we keep it for backward compatibility purpose.
However it remains a bit strange to use it on an HTTP proxy.

This patch may be backported to all versions supporting the HTX, i.e as far
as 2.0. But the part about the health-checks is only valid for the 2.2 and
upper.
2021-04-01 15:31:55 +02:00
Christopher Faulet
5eef0189c7 MINOR: config/proxy: Warn if a TCP proxy without backend is upgradable to HTTP
If a 'switch-mode http' tcp action is configured on a listener with no
backend, a warning is displayed to remember HTTP connections cannot be
routed to TCP servers. Indeed, backend connection is still established using
the proxy mode.
2021-04-01 13:24:34 +02:00
Christopher Faulet
3b6446f4d9 MINOR: config/proxy: Don't warn for HTTP rules in TCP if 'switch-mode http' set
Warnings about ignored HTTP directives in a TCP proxy are inhibited if at
least one switch-mode tcp action is configured to perform HTTP upgraded.
2021-04-01 13:22:42 +02:00
Christopher Faulet
ae863c62e3 MEDIUM: Add tcp-request switch-mode action to perform HTTP upgrade
It is now possible to perform HTTP upgrades on a TCP stream from the
frontend side. To do so, a tcp-request content rule must be defined with the
switch-mode action, specifying the mode (for now, only http is supported)
and optionnaly the proto (h1 or h2).

This way it could be possible to set HTTP directives on a TCP frontend which
will only be evaluated if an upgrade is performed. This new way to perform
HTTP upgrades should replace progressively the old way, consisting to route
the request to an HTTP backend. And it should be also a good start to remove
all HTTP processing from tcp-request content rules.

This action is terminal, it stops the ruleset evaluation. It is only
available on proxy with the frontend capability.

The configuration manual has been updated accordingly.
2021-04-01 13:17:19 +02:00
Christopher Faulet
6c1fd987f6 MINOR: stream: Handle stream HTTP upgrade in a dedicated function
The code responsible to perform an HTTP upgrade from a TCP stream is moved
in a dedicated function, stream_set_http_mode().

The stream_set_backend() function is slightly updated, especially to
correctly set the request analysers.
2021-04-01 11:06:48 +02:00
Christopher Faulet
75f619ad92 MINOR: http-ana: Simplify creation/destruction of HTTP transactions
Now allocation and initialization of HTTP transactions are performed in a
unique function. Historically, there were two functions because the same TXN
was reset for K/A connections in the legacy HTTP mode. Now, in HTX, K/A
connections are handled at the mux level. A new stream, and thus a new TXN,
is created for each request. In addition, the function responsible to end
the TXN is now also reponsible to release it.

So, now, http_create_txn() and http_destroy_txn() must be used to create and
destroy an HTTP transaction.
2021-04-01 11:06:48 +02:00
Christopher Faulet
c2ac5e4f27 MINOR: filters/http-ana: Decide to filter HTTP headers in HTTP analysers
It is just a small cleanup. AN_REQ_FLT_HTTP_HDRS and AN_RES_FLT_HTTP_HDRS
analysers are now set in HTTP analysers at the same place
AN_REQ_HTTP_XFER_BODY and AN_RES_HTTP_XFER_BODY are set.
2021-04-01 11:06:48 +02:00
Christopher Faulet
1bb6afa35d MINOR: stream: Use stream type instead of proxy mode when appropriate
We now use the stream instead of the proxy to know if we are processing HTTP
data or not. If the stream is an HTX stream, it means we are dealing with
HTTP data. It is more accurate than the proxy mode because when an HTTP
upgrade is performed, the proxy is not changed and only the stream may be
used.

Note that it was not a problem to rely on the proxy because HTTP upgrades
may only happen when an HTTP backend was set. But, we will add the support
of HTTP upgrades on the frontend side, after te tcp-request rules
evaluation.  In this context, we cannot rely on the proxy mode.
2021-04-01 11:06:48 +02:00
Christopher Faulet
28da3f5131 MEDIUM: mux-pt: Expose passthrough in the list of supported mux protocols
Add "none" in the list of supported mux protocols. It relies on the
passthrough multiplexer and use almost the same mux_ops structure. Only the
flags differ because this "new" mux does not support the upgrades. "none"
was chosen to explicitly stated there is not processing at the mux level.

Thus it is now possible to set "proto none" or "check-proto none" on
bind/server lines, depending on the context. However, when set, no upgrade
to HTTP is performed. It may be a way to disable HTTP upgrades per bind
line.
2021-04-01 11:06:48 +02:00
Christopher Faulet
3f612f7e4d MEDIUM: mux-h1: Expose h1 in the list of supported mux protocols
Add "h1" in the list of supported mux protocols. It relies on the H1
multiplexer and use the almost the same mux_ops structure. Only the flags
differ because this "new" mux does not support the upgrades.

Thus it is now possible to set "proto h1" or "check-proto h1" on bind/server
lines, depending on the context. However, when set, no upgrade to HTTP/2 is
performed. It may be a way to disable implicit HTTP/2 upgrades per bind
line.
2021-04-01 11:06:47 +02:00
Christopher Faulet
7a9e362b90 MINOR: mux-pt: Don't perform implicit HTTP upgrade if not supported by mux
For now this tests is useless, but if the PT muliplexer is flagged to
explicitly not support the upgrades to HTTP, an error is returned.
2021-04-01 11:06:47 +02:00
Christopher Faulet
143e9e5888 MINOR: mux-h1: Don't perform implicit HTTP/2 upgrade if not supported by mux
For now this tests is useless, but if the H1 muliplexer is flagged to
explicitly not support the upgrades to HTTP/2, an error is returned.
2021-04-01 11:06:47 +02:00
Christopher Faulet
a460057f2e MINOR: muxes: Add a flag to notify a mux does not support any upgrade
MX_FL_NO_UPG flag may now be set on a multiplexer to explicitly disable
upgrades from this mux. For now, it is set on the FCGI multiplexer because
it is not supported and there is no upgrade on backend-only multiplexers. It
is also set on the H2 multiplexer because it is clearly not supported.
2021-04-01 11:06:47 +02:00
Christopher Faulet
bb7abede93 BUG/MINOR: config: Add warning for http-after-response rules in TCP mode
No warning is emitted if some http-after-response rules are configured on a
TCP proxy while such warning messages are emitted for other HTTP ruleset in
same condition. It is just an oversight.

This patch may be backported as far as 2.2.
2021-04-01 11:06:47 +02:00
Christopher Faulet
97b3a61449 BUG/MINOR: stream: Properly handle TCP>H1>H2 upgrades in http_wait_for_request
When a TCP stream is first upgraded to H1 and then to H2, we must be sure to
inhibit any connect and to properly handle the TCP stream destruction.

When the TCP stream is upgraded to H1, the HTTP analysers are set. Thus
http_wait_for_request() is called. In this case, the server connection must
be blocked, waiting for the request analysis. Otherwise, a server may be
assigned to the stream too early. It is especially a problem if the stream
is finally destroyed because of an implicit upgrade to H2.

In this case, the stream processing must be properly aborted to not have a
stalled stream. Thus, if a shutdown is detected in http_wait_for_request()
when an HTTP upgrade is performed, the stream is aborted.

It is a 2.4-specific bug. No backport is needed.
2021-04-01 11:06:47 +02:00
Christopher Faulet
57e4a1bf44 MINOR: stream: Be sure to set HTTP analysers when creating an HTX stream
Always set frontend HTTP analysers when an HTX stream is created. It is only
useful in case a destructive HTTP upgrades (TCP>H2) because the frontend is
a TCP proxy.

In fact, to be strict, we must only set these analysers when the upgrade is
performed before setting the backend (it is not supported yet, but this
patch is required to do so), in the frontend part. If the upgrade happens
when the backend is set, it means the HTTP processing is just the backend
buisness. But there is no way to make the difference when a stream is
created, at least for now.
2021-04-01 11:06:47 +02:00
Christopher Faulet
e13ee703d2 MINOR: frontend: Create HTTP txn for HTX streams
When an HTX stream is created, be sure to always create the HTTP txn object,
regardless of the ".http_needed" value of the frontend. That happens when a
destructive HTTP upgrades is performed (TCP>H2). The frontend is a TCP
proxy. If there is no dependency on the HTTP part, the HTTP transaction is
not created at this stage but only when the backend is set. For now, it is
not a problem. But an HTTP txn will be mandatory to fully support TCP to
HTTP upgrades after frontend tcp-request rules evaluation.
2021-04-01 11:06:47 +02:00
Christopher Faulet
f0d7eb2f4f MINOR: stream: Don't trigger errors on destructive HTTP upgrades
When a TCP stream is upgraded to H2 stream, a destructive upgrade is
performed. It means the TCP stream is silently released while a new one is
created. It is of course more complicated but it is what we observe from the
stream point of view.

That was performed by returning an error when the backend was set. It is
neither really elegant nor accurate. So now, instead of returning an error
from stream_set_backend() in case of destructive HTTP upgrades, the TCP
stream processing is aborted and no error is reported. However, the result
is more or less the same.
2021-04-01 11:06:39 +02:00
Christopher Faulet
ceab1ed86c BUG/MINOR: mux-h2: Don't emit log twice if an error occurred on the preface
sess_log() was called twice if an error occurred on the preface parsing, in
h2c_frt_recv_preface() and in h2_process_demux().

This patch must be backported as far as 2.0.
2021-04-01 08:56:07 +02:00
Willy Tarreau
645dc08533 BUG/MINOR: http_fetch: make hdr_ip() resistant to empty fields
The fix in commit 7b0e00d94 ("BUG/MINOR: http_fetch: make hdr_ip() reject
trailing characters") made hdr_ip() more sensitive to empty fields, for
example if a trusted proxy incorrectly sends the header with an empty
value, we could return 0.0.0.0 which is not correct. Let's make sure we
only assign an IPv4 type here when a non-empty address was found.

This should be backported to all branches where the fix above was
backported.
2021-03-31 11:45:42 +02:00
Willy Tarreau
4bfc6630ba CLEANUP: socket: replace SOL_IP/IPV6/TCP with IPPROTO_IP/IPV6/TCP
Historically we've used SOL_IP/SOL_IPV6/SOL_TCP everywhere as the socket
level value in getsockopt() and setsockopt() but as we've seen over time
it regularly broke the build and required to have them defined to their
IPPROTO_* equivalent. The Linux ip(7) man page says:

   Using the SOL_IP socket options level isn't portable; BSD-based
   stacks use the IPPROTO_IP level.

And it indeed looks like a pure linuxism inherited from old examples and
documentation. strace also reports SOL_* instead of IPPROTO_*, which does
not help... A check to linux/in.h shows they have the same values. Only
SOL_SOCKET and other non-IP values make sense since there is no IPPROTO
equivalent.

Let's get rid of this annoying confusion by removing all redefinitions of
SOL_IP/IPV6/TCP and using IPPROTO_* instead, just like any other operating
system. This also removes duplicated tests for the same value.

Note that this should not result in exposing syscalls to other OSes
as the only ones that were still conditionned to SOL_IPV6 were for
IPV6_UNICAST_HOPS which already had an IPPROTO_IPV6 equivalent, and
IPV6_TRANSPARENT which is Linux-specific.
2021-03-31 08:59:34 +02:00
Willy Tarreau
da23195785 BUILD: tcp: use IPPROTO_IPV6 instead of SOL_IPV6 on FreeBSD/MacOS
Lukas reported in issue #1203 that the previous fix for silent-drop in
commit ab79ee8b1 ("BUG/MINOR: tcp: fix silent-drop workaround for IPv6")
breaks the build on FreeBSD/MacOS due to SOL_IPV6 not being defined. On
these platforms, IPPROTO_IPV6 must be used instead, so this should fix
it.

This needs to be backported to whatever version the fix above is backported
to.
2021-03-31 08:29:27 +02:00
Willy Tarreau
ab79ee8b11 BUG/MINOR: tcp: fix silent-drop workaround for IPv6
As reported in github issue #1203 the TTL-based workaround that is used
when permissions are insufficient for the TCP_REPAIR trick does not work
for IPv6 because we're using only SOL_IP with IP_TTL. In IPv6 we have to
use SOL_IPV6 and IPV6_UNICAST_HOPS. Let's pick the right one based on the
source address's family.

This may be backported to all versions.
2021-03-30 19:00:49 +02:00
Willy Tarreau
b48e7c0016 BUG/MEDIUM: time: make sure to always initialize the global tick
The issue with non-rotating freq counters was addressed in commit 8cc586c73
("BUG/MEDIUM: freq_ctr/threads: use the global_now_ms variable") using the
global date. But an issue remained with the comparison of the most recent
time. Since the initial time in the structure is zero, the tick_is_lt()
works on half of the periods depending on the first date an entry is
touched. And the wrapping happened last night:

  $ date --date=@$(((($(date +%s) * 1000) & -0x8000000) / 1000))
  Mon Mar 29 23:59:46 CEST 2021

So users of the last fix (backported to 2.3.8) may experience again an
always increasing rate for the next 24 days if they restart their process.

Let's always update the time if the latest date was not updated yet. It
will likely be simplified once the function is reorganized but this will
do the job for now.

Note that since this timer is only used by freq counters, no other
sub-system is affected. The bug can easily be tested with this config
during the right time period (i.e. today to today+24 days + N*49.7 days):

  global
    stats socket /tmp/sock1

  frontend web
    bind :8080
    mode http
    http-request track-sc0 src
    stick-table type ip size 1m expire 1h store http_req_rate(2s)

Issuing 'socat - /tmp/sock1  <<< "show table web"' should show a stable
rate after 2 seconds.

The fix must be backported to 2.3 and any other version the fix above
goes into.

Thanks to Thomas SIMON and Sander Klein for quickly reporting this issue
with a working reproducer.
2021-03-30 18:28:25 +02:00
Florian Apolloner
39272c28bf BUG/MINOR: stats: Apply proper styles in HTML status page.
When a backend is in status DOWN and going UP it is currently displayed
as yellow ("active UP, going down") instead of orange ("active DOWN, going
UP"). This patches restyles the table rows to actually match the
legend.

This may be backported to any version, the issue appeared in 1.7-dev2
with commit 0c378efe8 ("MEDIUM: stats: compute the color code only in
the HTML form").
2021-03-30 16:57:22 +02:00
Christopher Faulet
50623029f8 BUG/MINOR: payload: Wait for more data if buffer is empty in payload/payload_lv
In payload() and payload_lv() sample fetches, if the buffer is empty, we
must wait for more data by setting SMP_F_MAY_CHANGE flag on the sample.
Otherwise, when it happens in an ACL, nothing is returned (because the
buffer is empty) and the ACL is considered as finished (success or failure
depending on the test).

As a workaround, the buffer length may be tested first. For instance :

    tcp-request inspect-delay 1s
    tcp-request content reject unless { req.len gt 0 } { req.payload(0,0),fix_is_valid }

instead of :

    tcp-request inspect-delay 1s
    tcp-request content reject if ! { req.payload(0,0),fix_is_valid }

This patch must be backported as far as 2.2.
2021-03-29 11:47:53 +02:00
Willy Tarreau
9b9f8477f8 MEDIUM: backend: use a trylock to grab a connection on high FD counts as well
Commit b1adf03df ("MEDIUM: backend: use a trylock when trying to grab an
idle connection") solved a contention issue on the backend under normal
condition, but there is another one further, which only happens when the
number of FDs in use is considered too high, and which obviously causes
random crashes with just 16 threads once the number of FDs is about to be
exhausted.

Like the aforementioned patch, this one should be backported to 2.3.
2021-03-27 09:39:23 +01:00
Ilya Shipitsin
2c481d0105 BUILD: ssl: use EVP_CIPH_GCM_MODE macro instead of HA_OPENSSL_VERSION
EVP_CIPH_GCM_MODE was introduced in bdaa54155c
together with EVP support for AES-GCM.
2021-03-26 23:16:25 +01:00
Willy Tarreau
b8bd1ee893 MEDIUM: cli: add a new experimental "set var" command
set var <name> <expression>
  Allows to set or overwrite the process-wide variable 'name' with the result
  of expression <expression>. Only process-wide variables may be used, so the
  name must begin with 'proc.' otherwise no variable will be set. The
  <expression> may only involve "internal" sample fetch keywords and converters
  even though the most likely useful ones will be str('something') or int().
  Note that the command line parser doesn't know about quotes, so any space in
  the expression must be preceeded by a backslash. This command requires levels
  "operator" or "admin". This command is only supported on a CLI connection
  running in experimental mode (see "experimental-mode on").

Just like for "set-var" in the global section, the command uses a temporary
dummy proxy to create a temporary "set-var(name)" rule to assign the value.

The reg test was updated to verify that an updated global variable is properly
reflected in subsequent HTTP responses.
2021-03-26 16:57:43 +01:00
Willy Tarreau
c35eb38f1d MINOR: vars/cli: add a "get var" CLI command to retrieve global variables
Process-wide variables can now be displayed from the CLI using "get var"
followed by the variable name. They must all start with "proc." otherwise
they will not be found. The output is very similar to the one of the
debug converter, with a type and value being reported for the embedded
sample.

This command is limited to clients with the level "operator" or higher,
since it can possibly expose traffic-related data.
2021-03-26 16:52:13 +01:00
Willy Tarreau
2f836de100 MINOR: action: add a new ACT_F_CLI_PARSER origin designation
In order to process samples from the command line interface we'll need
rules as well, and these rules will have to be marked as coming from
the CLI parser. This new origin is used for this.
2021-03-26 16:34:53 +01:00
Willy Tarreau
db5e0dbea9 MINOR: sample: add a new CLI_PARSER context for samples
In order to prepare for supporting calling sample expressions from the
CLI, let's create a new CLI_PARSER parsing context. This one supports
constants and internal samples only.
2021-03-26 16:34:53 +01:00
Willy Tarreau
13d2ba2a82 MEDIUM: vars: add support for a "set-var" global directive
While we do support process-wide variables ("proc.<name>"), there was
no way to preset them from the configuration. This was particularly
limiting their usefulness since configs involving them always had to
first check if the variable was set prior to performing an operation.

This patch adds a new "set-var" directive in the global section that
supports setting the proc.<name> variables from an expression, like
other set-var actions do. The syntax however follows what is already
being done for setenv, which consists in having one argument for the
variable name and another one for the expression.

Only "constant" expressions are allowed here, such as "int", "str"
etc, combined with arithmetic or string converters, and variable
lookups. A few extra sample fetch keywords like "date", "rand" and
"uuid" are also part of the constant expressions and may make sense
to allow to create a random key or differentiate processes.

The way it was done consists in parsing a dummy rule an executing the
expression in the CFG_PARSE context, then releasing the expression.
This is safe because the sample that variables store does not hold a
back pointer to expression that created them.
2021-03-26 16:34:53 +01:00
Willy Tarreau
01d580ae86 MINOR: action: add a new ACT_F_CFG_PARSER origin designation
In order to process samples from the config file we'll need rules as
well, and these rules will have to be marked as coming from the
config parser. This new origin is used for this.
2021-03-26 16:23:45 +01:00
Willy Tarreau
f9a7a8fd8e MINOR: sample: add a new CFG_PARSER context for samples
We'd sometimes like to be able to process samples while parsing
the configuration based on purely internal thing but that's not
possible right now. Let's add a new CFG_PARSER context for samples
which only permits constant samples (i.e. those which do not change
in the process' life and which are stable during config parsing).
2021-03-26 16:23:45 +01:00
Willy Tarreau
0209c97038 MINOR: sample: mark the truly constant sample fetch keywords as such
A number of keywords are really constant and safe to use at config
time. This is the case for str(), int() etc but also env(), hostname(),
nbproc() etc. By extension a few other ones which can be useful to
preset values in a configuration were enabled as well, like data(),
rand() or uuid(). At the moment this doesn't change anything as they
are still only usable from runtime rules.

The "var()" keyword was also marked as const as it can definitely
return stable stuff at boot time.
2021-03-26 16:23:45 +01:00
Willy Tarreau
be2159b946 MINOR: sample: add a new SMP_SRC_CONST sample capability
This level indicates that everything it constant in the expression during
the whole process' life and that it may safely be used at config parsing
time.
2021-03-26 16:23:45 +01:00
Willy Tarreau
77e6a4ef0f MINOR: sample: make smp_resolve_args() return an allocate error message
For now smp_resolve_args() complains on stderr via ha_alert(), but if we
want to make it a bit more dynamic, we need it to return errors in an
allocated message. Let's pass it an error pointer and have it fill it.
On return we indent the output if it contains more than one line.
2021-03-26 16:23:45 +01:00
Willy Tarreau
e26cd0b46c CLEANUP: sample: remove duplicate "stopping" sample fetch keyword
The "stopping" sample fetch keyword was accidently duplicated in 1.9
by commit 70fe94419 ("MINOR: sample: add cpu_calls, cpu_ns_avg,
cpu_ns_tot, lat_ns_avg, lat_ns_tot"). This has no effect so no
backport is needed.
2021-03-26 16:23:45 +01:00
Willy Tarreau
f26db14dfb MINOR: vars: make the var() sample fetch keyword depend on nothing
This sample fetch doesn't require any L4 client session in practice, as
get_var() now checks for the session. This is important to remove this
dependency in order to support accessing variables in scope "proc" from
anywhere.
2021-03-26 16:23:45 +01:00
Willy Tarreau
a07d61be4c MINOR: vars: make get_vars() allow the session to be null
In order to support manipulating variables from outside a session,
let's make get_vars() not assume that the session is always set.
2021-03-26 16:23:45 +01:00
Amaury Denoyelle
704ba1d63e MINOR: lua: properly allocate the lua Socket servers
Instantiate both lua Socket servers tcp/ssl using standard function
new_server. There is currently no need to tune their settings except to
activate the ssl mode with noverify for the second one. Both servers are
freed with the free_server function.
2021-03-26 15:28:33 +01:00
Amaury Denoyelle
239fdbf548 MINOR: lua: properly allocate the lua Socket proxy
Replace static initialization of the lua Socket proxy with the standard
function alloc_new_proxy. The settings proxy are properly applied thanks
to PR_CAP_LUA. The proxy is freed with the free_proxy function.
2021-03-26 15:28:33 +01:00
Amaury Denoyelle
6f26faecd8 MINOR: proxy: define cap PR_CAP_LUA
Define a new cap PR_CAP_LUA. It can be used to allocate the internal
proxy for lua Socket class. This cap overrides default settings for
preferable values in the lua context.
2021-03-26 15:28:33 +01:00
Amaury Denoyelle
27fefa1967 MINOR: proxy: implement a free_proxy function
Move all liberation code related to a proxy in a dedicated function
free_proxy in proxy.c. For now, this function is only called in
haproxy.c. In the future, it will be used to free the lua proxy.

This helps to clean up haproxy.c.
2021-03-26 15:28:33 +01:00
Amaury Denoyelle
476b9ad97a REORG: split proxy allocation functions
Create a new function parse_new_proxy specifically designed to allocate
a new proxy from the configuration file and copy settings from the
default proxy.

The function alloc_new_proxy is reduced to a minimal allocation. It is
used for default proxy allocation and could also be used for internal
proxies such as the lua Socket proxy.
2021-03-26 15:28:33 +01:00
Amaury Denoyelle
68fd7e43d3 REORG: global: move free acl/action in their related source files
Move deinit_acl_cond and deinit_act_rules from haproxy.c respectively in
acl.c and action.c. The name of the functions has been slightly altered,
replacing the prefix deinit_* by free_* to reflect their purpose more
clearly.

This change has been made in preparation to the implementation of a free
proxy function. As a side-effect, it helps to clean up haproxy.c.
2021-03-26 15:28:33 +01:00
Amaury Denoyelle
ce44482fe5 REORG: global: move initcall register code in a dedicated file
Create a new module init which contains code related to REGISTER_*
macros for initcalls. init.h is included in api.h to make init code
available to all modules.

It's a step to clean up a bit haproxy.c/global.h.
2021-03-26 15:28:33 +01:00
Ilya Shipitsin
df627943a4 BUILD: ssl: introduce fine guard for ssl random extraction functions
SSL_get_{client,server}_random are supported in OpenSSL-1.1.0, BoringSSL,
LibreSSL-2.7.0

let us introduce HAVE_SSL_EXTRACT_RANDOM for that purpose
2021-03-26 15:19:07 +01:00
Remi Tricot-Le Breton
bc2c386992 BUG/MINOR: ssl: Prevent removal of crt-list line if the instance is a default one
If the first active line of a crt-list file is also the first mentioned
certificate of a frontend that does not have the strict-sni option
enabled, then its certificate will be used as the default one. We then
do not want this instance to be removable since it would make a frontend
lose its default certificate.
Considering that a crt-list file can be used by multiple frontends, and
that its first mentioned certificate can be used as default certificate
for only a subset of those frontends, we do not want the line to be
removable for some frontends and not the others. So if any of the ckch
instances corresponding to a crt-list line is a default instance, the
removal of the crt-list line will be forbidden.

It can be backported as far as 2.2.
2021-03-26 13:06:39 +01:00
Remi Tricot-Le Breton
8218aed90e BUG/MINOR: ssl: Fix update of default certificate
The default SSL_CTX used by a specific frontend is the one of the first
ckch instance created for this frontend. If this instance has SNIs, then
the SSL context is linked to the instance through the list of SNIs
contained in it. If the instance does not have any SNIs though, then the
SSL_CTX is only referenced by the bind_conf structure and the instance
itself has no link to it.
When trying to update a certificate used by the default instance through
a cli command, a new version of the default instance was rebuilt but the
default SSL context referenced in the bind_conf structure would not be
changed, resulting in a buggy behavior in which depending on the SNI
used by the client, he could either use the new version of the updated
certificate or the original one.

This patch adds a reference to the default SSL context in the default
ckch instances so that it can be hot swapped during a certificate
update.

This should fix GitHub issue #1143.

It can be backported as far as 2.2.
2021-03-26 13:06:29 +01:00
Willy Tarreau
62592ad967 BUG/MEDIUM: mux-h1: make h1_shutw_conn() idempotent
In issue #1197, Stphane Graber reported a rare case of crash that
results from an attempt to close an already closed H1 connection. It
indeed looks like under some circumstances it should be possible to
call the h1_shutw_conn() function more than once, though these
conditions are not very clear.

Without going through a deep analysis of all possibilities, one
potential case seems to be a detach() called with pending output data,
causing H1C_F_ST_SHUTDOWN to be set on the connection, then h1_process()
being immediately called on I/O, causing h1_send() to flush these data
and call h1_shutw_conn(), and finally the upper stream calling cs_shutw()
hence h1_shutw(), which itself will call h1_shutw_conn() again while the
transport and control layers have already been released. But the whole
sequence is not certain as it's not very clear in which case it's
possible to leave h1_send() without the connection anymore (at least
the obuf is empty).

However what is certain is that a shutdown function must be idempotent,
so let's fix h1_shutw_conn() regarding this point. Stphane reported the
issue as far back as 2.0, so this patch should be backported this far.
2021-03-26 09:29:38 +01:00
Willy Tarreau
7b0e00d943 BUG/MINOR: http_fetch: make hdr_ip() reject trailing characters
The hdr_ip() sample fetch function will try to extract IP addresses
from a header field. These IP addresses are parsed using url2ipv4()
and if it fails it will fall back to inet_pton(AF_INET6), otherwise
will fail.

There is a small problem there which is that if a field starts with
an IP address and is immediately followed by some garbage, the IP
address part is still returned. This is a problem with fields such
as x-forwarded-for because it prevents detection of accidental
corruption or bug along the chain. For example, the following string:

   x-forwarded-for: 1.2.3.4; 5.6.7.8

or this one:

   x-forwarded-for: 1.2.3.4O    ( the last one being the letter 'O')

would still return "1.2.3.4" despite the trailing characters. This is
bad because it will silently cover broken code running on intermediary
proxies and may even in some cases allow haproxy to pass improperly
formatted headers after they were apparently validated, for example,
if someone extracts the address from this field to place it into
another one.

This issue would only affect the IPv4 parser, because the IPv6 parser
already uses inet_pton() which fails at the first invalid character and
rejects trailing port numbers.

In strict compliance with RFC7239, let's make sure that if there are any
characters left in the string, the parsing fails and makes hdr_ip()
return nothing. However, a special case has to be handled to support
IPv4 addresses followed by a colon and a valid port number, because till
now the parser used to implicitly accept them and it appears that this
practice, though rare, does exist at least in Azure:
   https://docs.microsoft.com/en-us/azure/application-gateway/how-application-gateway-works

This issue has always been there so the fix may be backported to all
versions. It will need the following commit in order to work as expected:

    MINOR: tools: make url2ipv4 return the exact number of bytes parsed

Many thanks to https://twitter.com/melardev and the BitMEX Security Team
for their detailed report.
2021-03-25 15:30:06 +01:00
Willy Tarreau
12e1027aa6 MINOR: tools: make url2ipv4 return the exact number of bytes parsed
The function's return value is currently used as a boolean but we'll
need it to return the number of bytes parsed. Right now it returns
it minus one, unless the last char doesn't match what is permitted.
Let's update this to make it more usable.
2021-03-25 15:18:47 +01:00
Christopher Faulet
a9a9e9aac9 BUG/MEDIUM: thread: Fix a deadlock if an isolated thread is marked as harmless
If an isolated thread is marked as harmless, it will loop forever in
thread_harmless_till_end() waiting no threads are isolated anymore. It never
happens because the current thread is isolated. To fix the bug, we exclude
the current thread for the test. We now wait for all other threads to leave
the rendez-vous point.

This bug only seems to occurr if HAProxy is compiled with DEBUG_UAF, when
pool_gc() is called. pool_gc() isolates the current thread, while
pool_free_area() set the thread as harmless when munmap is called.

This patch must be backported as far as 2.0.
2021-03-25 14:31:50 +01:00
Amaury Denoyelle
65bf600cc3 BUG/MEDIUM: release lock on idle conn killing on reached pool high count
Release the lock before calling mux destroy in connect_server when
trying to kill an idle connection because the pool high count has been
reached.

The lock must be released because the mux destroy will call
srv_release_conn which also takes the lock to remove the connection from
the tree. As the connection was already deleted from the tree at this
stage, it is safe to release the lock, and the removal in
srv_release_conn will be a noop.

It does not need to be backported because it is only present in the
current release. It has been introduced by
    5c7086f6b0
    MEDIUM: connection: protect idle conn lists with locks
2021-03-25 11:55:35 +01:00
Olivier Houchard
c23b33764e BUG/MEDIUM: fd: Take the fd_mig_lock when closing if no DWCAS is available.
In fd_delete(), if we're running with no double-width cas, take the
fd_mig_lock before setting thread_mask to 0 to make sure that
another thread calling fd_set_running() won't miss the new value of
thread_mask and set its bit in running_mask after we checked it.

This should be backported to 2.2 as part of the series fixing fd_delete().
2021-03-25 07:34:35 +01:00
Willy Tarreau
2d4232901c CLEANUP: fd: slightly simplify up _fd_delete_orphan()
Let's release the port range earlier so that all zeroes are grouped
together and that the compiler can slightly simplify the code.
2021-03-24 17:17:21 +01:00
Willy Tarreau
2c3f9818e8 BUG/MEDIUM: fd: do not wait on FD removal in fd_delete()
Christopher discovered an issue mostly affecting 2.2 and to a less extent
2.3 and above, which is that it's possible to deadlock a soft-stop when
several threads are using a same listener:

          thread1                             thread2

      unbind_listener()                   fd_set_running()
          lock(listener)                  listener_accept()
          fd_delete()                          lock(listener)
             while (running_mask);  -----> deadlock
          unlock(listener)

This simple case disappeared from 2.3 due to the removal of some locked
operations at the end of listener_accept() on the regular path, but the
architectural problem is still here and caused by a lock inversion built
around the loop on running_mask in fd_clr_running_excl(), because there
are situations where the caller of fd_delete() may hold a lock that is
preventing other threads from dropping their bit in running_mask.

The real need here is to make sure the last user deletes the FD. We have
all we need to know the last one, it's the one calling fd_clr_running()
last, or entering fd_delete() last, both of which can be summed up as
the last one calling fd_clr_running() if fd_delete() calls fd_clr_running()
at the end. And we can prevent new threads from appearing in running_mask
by removing their bits in thread_mask.

So what this patch does is that it sets the running_mask for the thread
in fd_delete(), clears the thread_mask, thus marking the FD as orphaned,
then clears the running mask again, and completes the deletion if it was
the last one. If it was not, another thread will pass through fd_clr_running
and will complete the deletion of the FD.

The bug is easily reproducible in 2.2 under high connection rates during
soft close. When the old process stops its listener, occasionally two
threads will deadlock and the old process will then be killed by the
watchdog. It's strongly believed that similar situations do exist in 2.3
and 2.4 (e.g. if the removal attempt happens during resume_listener()
called from listener_accept()) but if so, they should be much harder to
trigger.

This should be backported to 2.2 as the issue appeared with the FD
migration. It requires previous patches "fd: make fd_clr_running() return
the remaining running mask" and "MINOR: fd: remove the unneeded running
bit from fd_insert()".

Notes for backport: in 2.2, the fd_dodelete() function requires an extra
argument "do_close" indicating whether we want to remove and close the FD
(fd_delete) or just delete it (fd_remove). While this information is not
conveyed along the chain, we know that late calls always imply do_close=1
become do_close=0 exclusively results from fd_remove() which is only used
by the config parser and the master, both of which are single-threaded,
hence are always the last ones in the running_mask. Thus it is safe to
assume that a postponed FD deletion always implies do_close=1.

Thanks to Olivier for his help in designing this optimal solution.
2021-03-24 17:17:21 +01:00
Christopher Faulet
1e8433f594 BUG/MEDIUM: lua: Always init the lua stack before referencing the context
When a lua context is allocated, its stack must be initialized to NULL
before attaching it to its owner (task, stream or applet).  Otherwise, if
the watchdog is fired before the stack is really created, that may lead to a
segfault because we try to dump the traceback of an uninitialized lua stack.

It is easy to trigger this bug if a lua script do a blocking call while
another thread try to initialize a new lua context. Because of the global
lua lock, the init is blocked before the stack creation. Of course, it only
happens if the script is executed in the shared global context.

This patch must be backported as far as 2.0.
2021-03-24 16:36:36 +01:00
Christopher Faulet
cc2c4f8f4c BUG/MEDIUM: debug/lua: Use internal hlua function to dump the lua traceback
The commit reverts following commits:
  * 83926a04 BUG/MEDIUM: debug/lua: Don't dump the lua stack if not dumpable
  * a61789a1 MEDIUM: lua: Use a per-thread counter to track some non-reentrant parts of lua

Instead of relying on a Lua function to print the lua traceback into the
debugger, we are now using our own internal function (hlua_traceback()).
This one does not allocate memory and use a chunk instead. This avoids any
issue with a possible deadlock in the memory allocator because the thread
processing was interrupted during a memory allocation.

This patch relies on the commit "BUG/MEDIUM: debug/lua: Use internal hlua
function to dump the lua traceback". Both must be backported wherever the
patches above are backported, thus as far as 2.0
2021-03-24 16:35:23 +01:00
Christopher Faulet
d09cc519bd MINOR: lua: Slightly improve function dumping the lua traceback
The separator string is now configurable, passing it as parameter when the
function is called. In addition, the message have been slightly changed to
be a bit more readable.
2021-03-24 16:33:26 +01:00
Ilya Shipitsin
a0fd35b054 BUILD: ssl: guard ecdh functions with SSL_CTX_set_tmp_ecdh macro
let us use feature macro SSL_CTX_set_tmp_ecdh instead of comparing openssl
version
2021-03-24 09:52:37 +01:00
Remi Tricot-Le Breton
fb00f31af4 BUG/MINOR: ssl: Prevent disk access when using "add ssl crt-list"
If an unknown CA file was first mentioned in an "add ssl crt-list" CLI
command, it would result in a call to X509_STORE_load_locations which
performs a disk access which is forbidden during runtime. The same would
happen if a "ca-verify-file" or "crl-file" was specified. This was due
to the fact that the crt-list file parsing and the crt-list related CLI
commands parsing use the same functions.
The patch simply adds a new parameter to all the ssl_bind parsing
functions so that they know if the call is made during init or by the
CLI, and the ssl_store_load_locations function can then reject any new
cafile_entry creation coming from a CLI call.

It can be backported as far as 2.2.
2021-03-23 19:29:46 +01:00
Willy Tarreau
f23b1bc534 BUILD: tools: fix build error with new PA_O_DEFAULT_DGRAM
Previous commit 69ba35146 ("MINOR: tools: introduce new option
PA_O_DEFAULT_DGRAM on str2sa_range.") managed to introduce a
parenthesis imbalance that broke the build. No backport is needed.
2021-03-23 18:38:13 +01:00
Emeric Brun
69ba35146f MINOR: tools: introduce new option PA_O_DEFAULT_DGRAM on str2sa_range.
str2sa_range function options PA_O_DGRAM and PA_O_STREAM are used to
define the supported address types but also to set the default type
if it is not explicit. If the used address support both STREAM and DGRAM,
the default was always set to STREAM.

This patch introduce a new option PA_O_DEFAULT_DGRAM to force the
default to DGRAM type if it is not explicit in the address field
and both STREAM and DGRAM are supported. If only DGRAM or only STREAM
is supported, it continues to be considered as the default.
2021-03-23 15:32:22 +01:00
Willy Tarreau
8cc586c73f BUG/MEDIUM: freq_ctr/threads: use the global_now_ms variable
In commit a1ecbca0a ("BUG/MINOR: freq_ctr/threads: make use of the last
updated global time"), for period-based counters, the millisecond part
of the global_now variable was used as the date for the new period. But
it's wrong, it only works with sub-second periods as it wraps every
second, and for other periods the counters never rotate anymore.

Let's make use of the newly introduced global_now_ms variable instead,
which contains the global monotonic time expressed in milliseconds.

This patch needs to be backported wherever the patch above is backported.
It depends on previous commit "MINOR: time: also provide a global,
monotonic global_now_ms timer".
2021-03-23 09:03:37 +01:00
Willy Tarreau
6064b34be0 MINOR: time: also provide a global, monotonic global_now_ms timer
The period-based freq counters need the global date in milliseconds,
so better calculate it and expose it rather than letting all call
places incorrectly retrieve it.

Here what we do is that we maintain a new globally monotonic timer,
global_now_ms, which ought to be very close to the global_now one,
but maintains the monotonic approach of now_ms between all threads
in that global_now_ms is always ahead of any now_ms.

This patch is made simple to ease backporting (it will be needed for
a subsequent fix), but it also opens the way to some simplifications
on the time handling: instead of computing the local time and trying
to force it to the global one, we should soon be able to proceed in
the opposite way, that is computing the new global time an making the
local one just the latest snapshot of it. This will bring the benefit
of making sure that the global time is always ahead of the local one.
2021-03-23 09:01:37 +01:00
Willy Tarreau
e44989369d CLEANUP: quic: use pool_zalloc() instead of pool_alloc+memset
Two places used to alloc then zero the area, let's have the allocator do it.
2021-03-22 23:20:21 +01:00
Willy Tarreau
6922e550eb CLEANUP: tcpcheck: use pool_zalloc() instead of pool_alloc+memset
Two places used to alloc then zero the area, let's have the allocator do it.
2021-03-22 23:20:03 +01:00
Willy Tarreau
f208ac0616 CLEANUP: ssl: use pool_zalloc() in ssl_init_keylog()
This one used to alloc then zero the area, let's have the allocator do it.
2021-03-22 23:19:48 +01:00
Willy Tarreau
70490ebb12 CLEANUP: resolvers: use pool_zalloc() in resolv_link_resolution()
This one used to alloc then zero the area, let's have the allocator do it.
2021-03-22 23:19:28 +01:00
Willy Tarreau
3ab0a0bc88 CLEANUP: mailers: use pool_zalloc() in enqueue_one_email_alert()
This one used to alloc then zero the area, let's have the allocator do it.
2021-03-22 23:19:13 +01:00
Willy Tarreau
ec4cfc3835 CLEANUP: frontend: use pool_zalloc() in frontend_accept()
The capture buffers were allocated then zeroed, let's have the allocator
do it.
2021-03-22 23:18:54 +01:00
Willy Tarreau
c9ef9bc9a5 CLEANUP: spoe: use pool_zalloc() instead of pool_alloc+memset
Two places used to alloc then zero the area, let's have the allocator do it.
2021-03-22 23:18:26 +01:00
Willy Tarreau
1bbec3883a CLEANUP: filters: use pool_zalloc() in flt_stream_add_filter()
This one used to alloc then zero the area, let's have the allocator do it.
2021-03-22 23:17:56 +01:00
Willy Tarreau
d68d4f1002 MEDIUM: dynbuf: remove last usages of b_alloc_margin()
The function's purpose used to be to fail a buffer allocation if that
allocation wouldn't result in leaving some buffers available. Thus,
some allocations could succeed and others fail for the sole purpose of
trying to provide 2 buffers at once to process_stream(). But things
have changed a lot with 1.7 breaking the promise that process_stream()
would always succeed with only two buffers, and later the thread-local
pool caches that keep certain buffers available that are not accounted
for in the global pool so that local allocators cannot guess anything
from the number of currently available pools.

Let's just replace all last uses of b_alloc_margin() with b_alloc() once
for all.
2021-03-22 16:27:59 +01:00
Willy Tarreau
f499f50c8f 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.
2021-03-22 16:17:37 +01:00
Willy Tarreau
862ad82f22 CLEANUP: compression: do not test for buffer before calling b_alloc()
Now we know the function is idempotent, we don't need to run the
preliminary test anymore.
2021-03-22 16:16:22 +01:00
Willy Tarreau
b454e908e5 MINOR: ssl: use pool_alloc(), not pool_alloc_dirty()
pool_alloc_dirty() is the version below pool_alloc() that never performs
the memory poisonning. It should only be called directly for very large
unstructured areas for which enabling memory poisonning would not bring
anything but could significantly hurt performance (e.g. buffers). Using
this function here will not provide any benefit and will hurt the ability
to debug.

It would be desirable to backport this, although it does not cause any
user-visible bug, it just complicates debugging.
2021-03-22 15:35:53 +01:00
Willy Tarreau
acc5b011e5 MINOR: cache: use pool_alloc(), not pool_alloc_dirty()
pool_alloc_dirty() is the version below pool_alloc() that never performs
the memory poisonning. It should only be called directly for very large
unstructured areas for which enabling memory poisonning would not bring
anything but could significantly hurt performance (e.g. buffers). Using
this function here will not provide any benefit and will hurt the ability
to debug.

It would be desirable to backport this, although it does not cause any
user-visible bug, it just complicates debugging.
2021-03-22 15:35:53 +01:00
Willy Tarreau
18f43d85a0 MINOR: fcgi-app: use pool_alloc(), not pool_alloc_dirty()
pool_alloc_dirty() is the version below pool_alloc() that never performs
the memory poisonning. It should only be called directly for very large
unstructured areas for which enabling memory poisonning would not bring
anything but could significantly hurt performance (e.g. buffers). Using
this function here will not provide any benefit and will hurt the ability
to debug.

It would be desirable to backport this, although it does not cause any
user-visible bug, it just complicates debugging.
2021-03-22 15:35:53 +01:00
Willy Tarreau
f1a91292dc MINOR: spoe: use pool_alloc(), not pool_alloc_dirty()
pool_alloc_dirty() is the version below pool_alloc() that never performs
the memory poisonning. It should only be called directly for very large
unstructured areas for which enabling memory poisonning would not bring
anything but could significantly hurt performance (e.g. buffers). Using
this function here will not provide any real benefit, it only avoids the
area being poisonned before being zeroed. Ideally a pool_calloc() function
should be provided for this.
2021-03-22 15:35:53 +01:00
Willy Tarreau
5bfeb2139b MINOR: compression: use pool_alloc(), not pool_alloc_dirty()
pool_alloc_dirty() is the version below pool_alloc() that never performs
the memory poisonning. It should only be called directly for very large
unstructured areas for which enabling memory poisonning would not bring
anything but could significantly hurt performance (e.g. buffers). Using
this function here will not provide any benefit and will hurt the ability
to debug.

It would be desirable to backport this, although it does not cause any
user-visible bug, it just complicates debugging.
2021-03-22 15:35:53 +01:00
Amaury Denoyelle
3b1c9a39fd CLEANUP: mark defproxy as const on parse tune.fail-alloc
This fixes a gcc warning about a missing const on defproxy for
mem_parse_global_fail_alloc.

This is needed since the commit :

018251667e
CLEANUP: config: make the cfg_keyword parsers take a const for the
defproxy
2021-03-22 11:50:31 +01:00
Ilya Shipitsin
ba13f16aa2 CLEANUP: assorted typo fixes in the code and comments
This is 21st iteration of typo fixes
2021-03-20 09:28:58 +01:00
Olivier Houchard
26c51097d8 MEDIUM: quic: Fix build.
Put the ) at the right place.

This should fix github issue #1190.
2021-03-19 20:09:22 +01:00
Olivier Houchard
7ab6d8bdf3 MEDIUM: quic: Fix build.
Spell conn_xprt_start() correctly.

This should fix github issue #1189.
2021-03-19 19:48:53 +01:00
Christopher Faulet
83926a04fe BUG/MEDIUM: debug/lua: Don't dump the lua stack if not dumpable
When we try to dump the stack of a lua context, if it is not dumpable,
nothing is performed and a message is emitted instead. This happens when a
lua execution was interrupted inside a non-reentrant part.

This patch depends on following commit :

 * MEDIUM: lua: Use a per-thread counter to track some non-reentrant parts of lua

Thanks to this patch, we avoid a possible deadllock if the lua is
interrupted by the watchdog in the lua memory allocator, because realloc()
is not async-signal-safe.

Both patches must be backported as far as 2.0.
2021-03-19 16:19:59 +01:00
Christopher Faulet
a61789a1d6 MEDIUM: lua: Use a per-thread counter to track some non-reentrant parts of lua
Some parts of the Lua are non-reentrant. We must be sure to carefully track
these parts to not dump the lua stack when it is interrupted inside such
parts. For now, we only identified the custom lua allocator. If the thread
is interrupted during the memory allocation, we must not try to print the
lua stack wich also allocate memory. Indeed, realloc() is not
async-signal-safe.

In this patch we introduce a thread-local counter. It is incremented before
entering in a non-reentrant part and decremented when exiting. It is only
performed in hlua_alloc() for now.
2021-03-19 16:16:23 +01:00
Christopher Faulet
a561ffb978 CLEANUP: tcp-rules: Fix a typo in error messages about expect-netscaler-cip
It was misspelled (expect-netscaler-ip instead of expect-netscaler-cip). 2
commits are concerned :

 * db67b0ed7 MINOR: tcp-rules: suggest approaching action names on mismatch
 * 72d012fbd CLEANUP: tcp-rules: add missing actions in the tcp-request error message

The first one will not be backported, but the second one was backported as
far as 1.8. Thus this one may also be backported, but only the 2nd part
about the list of accepted keywords.
2021-03-19 15:41:16 +01:00
Olivier Houchard
dae6975498 MINOR: muxes: garbage collect the reset() method.
Now that connections aren't being reused when they failed, remove the
reset() method. It was unimplemented anywhere, except for H1 where it did
nothing, anyway.
2021-03-19 15:33:04 +01:00
Olivier Houchard
bc5ce9201a MEDIUM: connections: Implement a start() method in ssl_sock.
Add a start() method to ssl_sock. It is responsible with initiating the
SSL handshake, currently by just scheduling the tasklet, instead of doing
it in the init() method, when all the XPRT may not have been initialized.
2021-03-19 15:33:04 +01:00
Olivier Houchard
d54ede7d08 MEDIUM: connections: Implement a start() method for xprt_handshake.
Add a start_method to xprt_handshake. It schedules the tasklet that does
the handshake. This used to be done in xprt_handshake_add_xprt(), but that's
a much better place.
2021-03-19 15:33:04 +01:00
Olivier Houchard
1b3c931bff MEDIUM: connections: Introduce a new XPRT method, start().
Introduce a new XPRT method, start(). The init() method will now only
initialize whatever is needed for the XPRT to run, but any action the XPRT
has to do before being ready, such as handshakes, will be done in the new
start() method. That way, we will be sure the full stack of xprt will be
initialized before attempting to do anything.
The init() call is also moved to conn_prepare(). There's no longer any reason
to wait for the ctrl to be ready, any action will be deferred until start(),
anyway. This means conn_xprt_init() is no longer needed.
2021-03-19 15:33:04 +01:00
Olivier Houchard
ca1a57f022 MINOR: raw_sock: Add a close method.
Add a close() method, that explicitely cancels any subscription on the
connection, in preparation for future evolutions.
2021-03-19 15:33:04 +01:00
Emeric Brun
8af3bb0abf BUG/MINOR: protocol: add missing support of dgram unix socket.
The proto "uxdg" (UNIX DGRAM) was not declared, causing an error trying
to put a socket unix on "dgram-bind" into a log-forward section.

This patch introduces the missing "uxdg" protocol by adding proto_uxdg.c
which was fully created based on the code available for the other
protocols.

This patch should be backported to version 2.3 and above.
2021-03-18 18:30:29 +01:00
Amaury Denoyelle
304672320e MINOR: server: support keyword proto in 'add server' cli
Allow to specify the mux proto for a dynamic server. It must be
compatible with the backend mode to be accepted. The reg-tests has been
extended for this error case.
2021-03-18 16:22:10 +01:00
Amaury Denoyelle
fc465a54fd MINOR: server: enable standard options for dynamic servers
Enable a subset of server options to be used as keywords on the CLI
command 'add server'. These options are safe and can be applied
flawlessly for a dynamic server.
2021-03-18 16:22:10 +01:00
Amaury Denoyelle
f99f77a500 MEDIUM: server: implement 'add server' cli command
Add a new cli command 'add server'. This command is used to create a new
server at runtime attached on an existing backend. The syntax is the
following one :

$ add server <be_name>/<sv_name> [<kws>...]

This command is only available through experimental mode for the moment.

Currently, no server keywords are supported. They will be activated
individually when deemed properly functional and safe.

Another limitation is put on the backend load-balancing algorithm. The
algorithm must use consistent hashing to guarantee a minimal
reallocation of existing connections on the new server insertion.
2021-03-18 15:52:07 +01:00
Amaury Denoyelle
216a1ce3b9 MINOR: stats: export function to allocate extra proxy counters
Remove static qualifier on stats_allocate_proxy_counters_internal. This
function will be used to allocate extra counters at runtime for dynamic
servers.
2021-03-18 15:52:07 +01:00
Amaury Denoyelle
76e10e78bb MINOR: server: prepare parsing for dynamic servers
Prepare the server parsing API to support dynamic servers.
- define a new parsing flag to be used for dynamic servers
- each keyword contains a new field dynamic_ok to indicate if it can be
  used for a dynamic server. For now, no keyword are supported.
- do not copy settings from the default server for a new dynamic server.
- a dynamic server is created in a maintenance mode and requires an
  explicit 'enable server' command.
- a new server flag named SRV_F_DYNAMIC is created. This flag is set for
  all servers created at runtime. It might be useful later, for example
  to know if a server can be purged.
2021-03-18 15:51:12 +01:00
Amaury Denoyelle
30c0537f5a REORG: server: use flags for parse_server
Modify the API of parse_server function. Use flags to describe the type
of the parsed server instead of discrete arguments. These flags can be
used to specify if a server/default-server/server-template is parsed.
Additional parameters are also specified (parsing of the address
required, resolve of a name must be done immediately).

It is now unneeded to use strcmp on args[0] in parse_server. Also, the
calls to parse_server are more explicit thanks to the flags.
2021-03-18 15:37:05 +01:00
Amaury Denoyelle
cf58dd79e3 REORG: server: attach servers in parse_server
Move server linked into proxy backend list outside of _srv_parse_init to
parse_server.

This is groundwork for dynamic servers support. There will be two
differences in case of a dynamic server :
- the server will be attached to the proxy list only at the very end of the
  operations when everything is ok
- the server will be directly attached to the end of the server proxy
  list
2021-03-18 15:37:05 +01:00
Amaury Denoyelle
7d27efef23 REORG: server: rename internal functions from parse_server
Use a standard convention for the functions used through parse_server.
Use the prefix _srv_parse and specify their private scope in a comment.
2021-03-18 15:37:05 +01:00
Amaury Denoyelle
9394a9444e REORG: server: move alert traces in parse_server
Move every ha_alert calls in parsing functions into parse_server.
Parsing functions now support a pointer-to-string argument which will be
allocated with an error message if needed via memprintf.

parse_server has then the responsibility to display errors with ha_alert.

This is groundwork for dynamic server. No traces should be printed on
stderr as a response to a cli command. cli_err will replace ha_alert in
this case.
2021-03-18 15:37:05 +01:00
Amaury Denoyelle
a8f442e078 REORG: server: split parse_server
The huge parse_server function is splitted into two smaller ones.
* _srv_parse_init allocates a new server instance and parses the address
  parameter
* _srv_parse_kw parse the current server keyword

This simplify a bit the parse_server function. Besides, it will be
useful for dynamic server creation.
2021-03-18 15:37:05 +01:00
Amaury Denoyelle
3b89c11d4d MINOR: server: remove fastinter from mistyped kw list
This keyword is already present in server kw list from checks.c.
2021-03-18 15:37:05 +01:00
Amaury Denoyelle
587b71e402 REORG: server: move keywords in srv_kws
Move server-keyword hardcoded in parse_server into the srv_kws list of
server.c. Now every server keywords is checked through srv_find_kw. This
has the effect to reduce the size of parse_server. As a side-effect,
common kw list can be reduced.

This change has been made to be able to quickly discard these keywords
in case of a dynamic server.
2021-03-18 15:37:05 +01:00
Amaury Denoyelle
3efee6572f MINOR: cfgparse: always alloc idle conns task
The idle conn task is is a global task used to cleanup backend
connections marked for deletion. Previously, it was only only allocated
if at least one server in the configuration has idle connections.

This assumption won't be valid anymore when new servers can be created
at runtime with idle connections. Always allocate the global idle conn
task.
2021-03-18 15:37:05 +01:00
Amaury Denoyelle
828adf0121 REORG: server: add a free server function
Create a new server function named free_server. It can be used to
deallocate a server and its member.
2021-03-18 15:37:05 +01:00
Amaury Denoyelle
18487fb532 MINOR: cli: implement experimental-mode
Experimental mode is similar to expert-mode. It can be used to access to
features still in development.
2021-03-18 15:37:05 +01:00
Eric Salama
5ba8335186 MINOR: mworker/cli: alert the user if we enabled a master CLI but not the master-worker mode
Declaring a master CLI socket without activating the master-worker mode
is likely a user error, so we issue a warning.

This patch can be backported as far as 1.8.
2021-03-18 09:08:33 +01:00
Eric Salama
1b8dacc858 MINOR/BUG: mworker/cli: do not use the unix_bind prefix for the master CLI socket
If the configuration file contains a 'unix-bind prefix' directive, and
if we use the -S option and specify a UNIX socket path, the path of the
socket will be prepended with the value of the unix-bind prefix.

For instance, if we have 'unix-bind prefix /tmp/sockets/' and we use
'-S /tmp/master-socket' on the command line, we will get this error:

Starting proxy MASTER:
cannot bind UNIX socket (No such file or directory) [/tmp/sockets/tmp/master-socket]

So this patch adds an exception, and will ignore the unix-bind prefix
for the master CLI socket.

This patch can be backported as far as 1.9.
2021-03-18 09:08:19 +01:00
Willy Tarreau
a1ecbca0a5 BUG/MINOR: freq_ctr/threads: make use of the last updated global time
The freq counters were using the thread's own time as the start of the
current period. The problem is that in case of contention, it was
occasionally possible to perform non-monotonic updates on the edge of
the next second, because if the upfront thread updates a counter first,
it causes a rotation, then the second thread loses the race from its
older time, and tries again, and detects a different time again, but
in the past so it only updates the counter, then a third thread on the
new date would detect a change again, thus provoking a rotation again.

The effect was triple:
  - rare loss of stored values during certain transitions from one
    period to the next one, causing counters to report 0
  - half of the threads forced to go through the slow path every second
  - difficult convergence when using many threads where the CAS can fail
    a lot and we can observe N(N-1) attempts for N threads to complete

This patch fixes this issue in two ways:
  - first, it now makes use og the monotonic global_now value which also
    happens to be volatile and to carry the latest known time; this way
    time will never jump backwards anymore and only the first thread
    updates it on transition, the other ones do not need to.

  - second, re-read the time in the loop after each failure, because
    if the date changed in the counter, it means that one thread knows
    a more recent one and we need to update. In this case if it matches
    the new current second, the fast path is usable.

This patch relies on previous patch "MINOR: time: export the global_now
variable" and must be backported as far as 1.8.
2021-03-17 19:36:15 +01:00
Willy Tarreau
650f374f24 MINOR: time: export the global_now variable
This is the process-wide monotonic time that is used to update each
thread's own time. It may be required at a few places where a strictly
monotonic clock is required such as freq_ctr. It will be have to be
backported as a dependency of a forthcoming fix.
2021-03-17 19:25:47 +01:00
Christopher Faulet
59b2925733 BUG/MINOR: resolvers: Add missing case-insensitive comparisons of DNS hostnames
DNS hostname comparisons were fixed to be case-insensitive (see b17b88487
"BUG/MEDIUM: dns: Consider the fact that dns answers are
case-insensitive"). However 2 comparisons are still case-sensitive.

This patch must be backported as far as 1.8.
2021-03-16 11:25:04 +01:00
Willy Tarreau
31a3cea84f MINOR: cfgparse/proxy: also support spelling fixes on options
Some are not always easy to spot with "chk" vs "check" or hyphens at
some places and not at others. Now entering "option http-close" properly
suggests "httpclose" and "option tcp-chk" suggests "tcp-check". There's
no need to consider the proxy's capabilities, what matters is to figure
what related word the user tried to spell, and there are not that many
options anyway.
2021-03-15 11:14:57 +01:00
Willy Tarreau
ec197e83cd MINOR: cli: sort the suggestions by order of relevance
Now the suggested keywords are sorted with the most relevant ones first
instead of scanning them all in registration order and only dumping the
proposed ones:

- "tra"
   trace <module> [cmd [args...]] : manage live tracing
   operator       : lower the level of the current CLI session to operator
   user           : lower the level of the current CLI session to user
   show trace [<module>] : show live tracing state

- "pool"
   show pools     : report information about the memory pools usage
   add acl        : add acl entry
   del map        : delete map entry
   user           : lower the level of the current CLI session to user
   del acl        : delete acl entry

- "sh ta"
   show stat      : report counters for each proxy and server [desc|json|no-maint|typed|up]*
   show tasks     : show running tasks
   set table [id] : update or create a table entry's data
   show table [id]: report table usage stats or dump this table's contents
   trace <module> [cmd [args...]] : manage live tracing

- "sh state"
   show stat      : report counters for each proxy and server [desc|json|no-maint|typed|up]*
   set table [id] : update or create a table entry's data
   show table [id]: report table usage stats or dump this table's contents
   show servers state [id]: dump volatile server information (for backend <id>)
   show sess [id] : report the list of current sessions or dump this session
2021-03-15 10:39:45 +01:00
Willy Tarreau
a9aa628703 MINOR: cli: improve fuzzy matching to work on all remaining words at once
Till now the fuzzy matching would only work on the same number of words,
but this doesn't account for commands like "show servers conn" which
involve 3 words and were not proposed when entering only "show conn".
Let's improve the situation by building the two fingerprints separately
for the correct keyword sequence and the entered one, then compare them.
This can result in slightly larger variations due to the different string
lengths but is easily compensated for. Thanks to this, we can now see
"show servers conn" when entering "show conn", and the following choices
are relevant to correct typos:

- "show foo"
   show sess [id] : report the list of current sessions or dump this session
   show info      : report information about the running process [desc|json|typed]*
   show env [var] : dump environment variables known to the process
   show fd [num] : dump list of file descriptors in use
   show pools     : report information about the memory pools usage

- "show stuff"
   show sess [id] : report the list of current sessions or dump this session
   show info      : report information about the running process [desc|json|typed]*
   show stat      : report counters for each proxy and server [desc|json|no-maint|typed|up]*
   show fd [num] : dump list of file descriptors in use
   show tasks     : show running tasks

- "show stafe"
   show sess [id] : report the list of current sessions or dump this session
   show stat      : report counters for each proxy and server [desc|json|no-maint|typed|up]*
   show fd [num] : dump list of file descriptors in use
   show table [id]: report table usage stats or dump this table's contents
   show tasks     : show running tasks

- "show state"
   show stat      : report counters for each proxy and server [desc|json|no-maint|typed|up]*
   show servers state [id]: dump volatile server information (for backend <id>)

It's still visible that the shorter ones continue to easily match, such
as "show sess" not having much in common with "show foo" but what matters
is that the best candidates are definitely relevant. Probably that listing
them in match order would further help.
2021-03-15 10:33:45 +01:00
Willy Tarreau
714c4c14d1 MINOR: tools: do not sum squares of differences for word fingerprints
While sums of squares usually give excellent results in fixed-sise
patterns, they don't work well to compare different sized ones such
as when some sub-words are missing, because a word such as "server"
contains "er" twice, which will rsult in an extra distance of at
least 4 for just this e->r transition compared to another one missing
it. This is one of the main reasons why "show conn" only proposes
"show info" on the CLI. Maybe an improved approach consisting in
using squares only for exact same lengths would work, but it would
still make it difficult to spot reversed characters.
2021-03-15 09:44:53 +01:00
Willy Tarreau
9294e8822f MINOR: tools: improve word fingerprinting by counting presence
The distance between two words can be high due to a sub-word being missing
and in this case it happens that other totally unrealted words are proposed
because their average score looks lower thanks to being shorter. Here we're
introducing the notion of presence of each character so that word sequences
that contain existing sub-words are favored against the shorter ones having
nothing in common. In addition we do not distinguish being/end from a
regular delimitor anymore. That made it harder to spot inverted words.
2021-03-15 09:38:42 +01:00
Willy Tarreau
101df31503 BUG/MINOR: cfgparse: use the GLOBAL not LISTEN keywords list for spell checking
In commit a0e8eb8ca ("MINOR: cfgparse: suggest correct spelling for
unknown words in global section") we got the ability to locate a better
matching word in case of error. But it mistakenly used the CFG_LISTEN
class of words instead of CFG_GLOBAL, resulting in proposing unsuitable
matches in addition to the long hard-coded list. Now, "tune.dh-param"
correctly proposes "tune.ssl.default-dh-param".

No backport is needed.
2021-03-15 09:15:18 +01:00
Willy Tarreau
9c18747823 BUG/MEDIUM: cli: fix "help" crashing since recent spelling fixes
I somehow managed to re-break the "help" command in b736458bf ("MEDIUM:
cli: apply spelling fixes for known commands before listing them")
after fixing it once. A null-deref happens when checking the args
early in the processing.

No backport is needed as this was introduced in 2.4-dev12.
2021-03-13 12:25:43 +01:00
Willy Tarreau
7416314145 CLEANUP: task: make sure tasklet handlers always indicate their statuses
When tasklets were derived from tasks, there was no immediate need for
the scheduler to know their status after execution, and in a spirit of
simplicity they just started to always return NULL. The problem is that
it simply prevents the scheduler from 1) accounting their execution time,
and 2) keeping track of their current execution status. Indeed, a remote
wake-up could very well end up manipulating a tasklet that's currently
being executed. And this is the reason why those handlers have to take
the idle lock before checking their context.

In 2.5 we'll take care of making tasklets and tasks work more similarly,
but trouble is to be expected if we continue to propagate the trend of
returning NULL everywhere, especially if some fixes relying on a stricter
model later need to be backported. For this reason this patch updates all
known tasklet handlers to make them return NULL only when the tasklet was
freed. It has no effect for now and isn't even guaranteed to always be
100% safe but it puts the code into the right direction for this.
2021-03-13 11:30:19 +01:00
Willy Tarreau
4975d1482f CLEANUP: cli: rename the last few "stats_" to "cli_"
There were still a very small list of functions, variables and fields
called "stats_" while they were really purely CLI-centric. There's the
frontend called "stats_fe" in the global section, which instantiates a
"cli_applet" called "<CLI>" so it was renamed "cli_fe".

The "alloc_stats_fe" function cas renamed to "cli_alloc_fe" which also
better matches the naming convention of all cli-specific functions.

Finally the "stats_permission_denied_msg" used to return an error on
the CLI was renamed "cli_permission_denied_msg".

Now there's no more "stats_something" that designates the CLI.
2021-03-13 11:04:35 +01:00
Willy Tarreau
f14c7570d6 CLEANUP: cli: rename MAX_STATS_ARGS to MAX_CLI_ARGS
This is the number of args accepted on a command received on the CLI,
is has long been totally independent of stats and should not carry
this misleading "stats" name anymore.
2021-03-13 10:59:23 +01:00
Willy Tarreau
c57dcfe787 MINOR: cli: apply the fuzzy matching on the whole command instead of words
Now instead of comparing words at an exact position, we build a fingerprint
made of all of them, so that we can check for them in any position. For
example, "show conn serv" finds "show servers conn" and that "set servers
maxconn" proposes both "set server" and "set maxconn servers".
2021-03-12 19:09:19 +01:00
Willy Tarreau
e33c4b3c11 MINOR: tools: add the ability to update a word fingerprint
Instead of making a new one from scratch, let's support not wiping the
existing fingerprint and updating it, and to do the same char by char.
The word-by-word one will still result in multiple beginnings and ends,
but that will accurately translate word boundaries. The char-based one
has more flexibility and requires that the caller maintains the previous
char to indicate the transition, which also allows to insert delimiters
for example.
2021-03-12 19:09:19 +01:00
Willy Tarreau
b736458bfa MEDIUM: cli: apply spelling fixes for known commands before listing them
Entering "show tls" would still emit 35 entries. By measuring the distance
between all unknown words and the candidates, we can sort them and pick the
10 most likely candidates. This works reasonably well, as now "show tls"
only proposes "show tls-keys", "show threads", "show pools" and "show tasks".

If the distance is still too high or if a word is missing, the whole
prefix list continues to be dumped, thus "show" alone will still report
the entire list of commands beginning with "show".

It's still impossible to skip a word, for example "show conn" will not
propose "show servers conn" because the distance is calculated for each
word individually. Some changes to the distance calculation to support
updating an existing map could easily address this. But this is already
a great improvement.
2021-03-12 19:09:19 +01:00
Willy Tarreau
b96a74cbfd MINOR: cli: filter the list of commands to the matching part
The error message on the CLI has become unreadable due to the long list
and it's not even sorted, making it even harder to figure the right
command.

This patch starts by looking if some of the words match something known,
and if so, will limit the listing only to those commands that start like
the current one. The "help", "prompt" and "quit" commands are always
shown to help the user try something else. Now thanks to this, typing
"add" or "del" will only list "add acl", "add map" and not 50 lines
anymore.

As a small bonus, we won't print "Unknown command" anymore in response
to the "help" command.
2021-03-12 19:09:19 +01:00
Willy Tarreau
f3697dde2b MINOR: cli: print the error message in the parser function itself
By doing so we can report more accurate information about what's wrong.
As a first step, we already distinguish the case of expert-only commands
from other ones.
2021-03-12 19:09:19 +01:00
Willy Tarreau
91bc359571 MINOR: cli: test the appctx level for master access instead of comparing pointers
Now that the appctx contains the master level, it greatly simplifies
all the tests, as we can simply verify that keyword levels match the
effective level without having to cheat with applet pointers. This
also allows to fold the expert test in them.
2021-03-12 19:09:19 +01:00
Willy Tarreau
e283ee6265 MINOR: cli: set the ACCESS_MASTER* bits on the master bind_conf
Right now the code is a bit hackish, it tests for the keyword's level
flags but checks the applet's origin to compare the bits. Let's start
by properly setting the ACCESS_MASTER_ONLY and ACCESS_MASTER flags on
the master CLI's bind_conf so that they are automatically present
all the time.
2021-03-12 19:09:19 +01:00
Willy Tarreau
0609c9bde9 BUG/MINOR: cli: make sure "help", "prompt", "quit" are enabled at master level
These 3 commands are functionally valid both in master and worker CLIs.
However, while they do have a valid handler, they are not permitted by
the code and work partially by chance in the master:
  - "prompt" and "quit" are intercepted by the request analyser
  - "help" triggers an error, which results in displaying the error
    message

Let's make sure they are permitted so that we don't count errors there and
that we can report appropriate help.

This bug has always been there but it doesn't have any functional effect
at the moment since "help" can only show the error message. As such, there
is no need to backport it.
2021-03-12 19:09:19 +01:00
Christopher Faulet
db31b4486c CLEANUP: resolvers: Perform unsafe loop on requester list when possible
When answer list of a response is checked, it is useless to perform a safe
loop on the requester list.
2021-03-12 17:42:47 +01:00
Christopher Faulet
c392d461d6 CLEANUP: resolvers: Use ha_free() in srvrq_resolution_error_cb()
Two occurrences to "free(A);A=NULL;" may be replaced by a call to ha_free()
in the srvrq_resolution_error_cb() function.
2021-03-12 17:42:47 +01:00
Christopher Faulet
e8674c7184 MINOR: resolvers: Don't try to match immediatly renewed ADD items
The loop looking for existing ADD items to renew their last_seen must ignore
the items already renewed in the same loop. To do so, we rely on the
last_seen time. because it is now based on now_ms, it is safe.

Doing so avoid to match several time the same ADD item when the same IP
address is found in several ADD item. This reduces the number of extra DNS
resolutions.

This patch depends on "MINOR: resolvers: Use milliseconds for cached items
in resolver responses". Both may be backported as far as 2.2 if necessary.
2021-03-12 17:42:45 +01:00
Christopher Faulet
55c1c4053f MINOR: resolvers: Use milliseconds for cached items in resolver responses
The last time when an item was seen in a resolver responses is now stored in
milliseconds instead of seconds. This avoid some corner-cases at the
edges. This also simplifies time comparisons.
2021-03-12 17:41:28 +01:00
Christopher Faulet
d83a6df5cd BUG/MEDIUM: resolvers: Skip DNS resolution at startup if SRV resolution is set
At startup, if a SRV resolution is set for a server, no DNS resolution is
created. We must wait the first SRV resolution to know if it must be
triggered. It is important to do so for two reasons.

First, during a "classical" startup, a server based on a SRV resolution has
no hostname. Thus the created DNS resolution is useless. Best waiting the
first SRV resolution. It is not really a bug at this stage, it is just
useless.

Second, in the same situation, if the server state is loaded from a file,
its hosname will be set a bit later. Thus, if there is no additionnal record
for this server, because there is already a DNS resolution, it inhibits any
new DNS resolution. But there is no hostname attached to the existing DNS
resolution. So no resolution is performed at all for this server.

To avoid any problem, it is fairly easier to handle this special case during
startup. But this means we must be prepared to have no "resolv_requester"
field for a server at runtime.

This patch must be backported as far as 2.2.
2021-03-12 17:41:28 +01:00
Christopher Faulet
0efc0993ec BUG/MEDIUM: resolvers: Don't release resolution from a requester callbacks
Another way to say it: "Safely unlink requester from a requester callbacks".

Requester callbacks must never try to unlink a requester from a resolution, for
the current requester or another one. First, these callback functions are called
in a loop on a request list, not necessarily safe. Thus unlink resolution at
this place, may be unsafe. And it is useless to try to make these loops safe
because, all this stuff is placed in a loop on a resolution list. Unlink a
requester may lead to release a resolution if it is the last requester.

However, the unkink is necessary because we cannot reset the server state
(hostname and IP) with some pending DNS resolution on it. So, to workaround
this issue, we introduce the "safe" unlink. It is only performed from a
requester callback. In this case, the unlink function never releases the
resolution, it only reset it if necessary. And when a resolution is found
with an empty requester list, it is released.

This patch depends on the following commits :

 * MINOR: resolvers: Purge answer items when a SRV resolution triggers an error
 * MINOR: resolvers: Use a function to remove answers attached to a resolution
 * MINOR: resolvers: Directly call srvrq_update_srv_state() when possible
 * MINOR: resolvers: Add function to change the srv status based on SRV resolution

All the series must be backported as far as 2.2. It fixes a regression
introduced by the commit b4badf720 ("BUG/MINOR: resolvers: new callback to
properly handle SRV record errors").

don't release resolution from requester cb
2021-03-12 17:41:28 +01:00
Christopher Faulet
6b117aed49 MINOR: resolvers: Directly call srvrq_update_srv_state() when possible
When the server status must be updated from the result of a SRV resolution,
we can directly call srvrq_update_srv_state(). It is simpler and this avoid
a test on the server DNS resolution.

This patch is mandatory for the next commit. It also rely on "MINOR:
resolvers: Directly call srvrq_update_srv_state() when possible".
2021-03-12 17:41:28 +01:00
Christopher Faulet
5efdef24c1 MINOR: resolvers: Add function to change the srv status based on SRV resolution
srvrq_update_srv_status() update the server status based on result of SRV
resolution. For now, it is only used from snr_update_srv_status() when
appropriate.
2021-03-12 17:41:28 +01:00
Christopher Faulet
51d5e3bda7 MINOR: resolvers: Purge answer items when a SRV resolution triggers an error
When a SRV request trigger an error, if we decide to handle the error
because last_valid duration is expired, the answer list may be purged. All
items are considered as obsolete.
2021-03-12 17:41:28 +01:00
Christopher Faulet
1dec5c7934 MINOR: resolvers: Use a function to remove answers attached to a resolution
resolv_purge_resolution_answer_records() must be used to removed all answers
attached to a resolution. For now, it is only used when a resolution is
released.
2021-03-12 17:41:28 +01:00
Christopher Faulet
3e0600fbbf BUG/MEDIUM: resolvers: Trigger a DNS resolution if an ADD item is obsolete
When a ADD item attached to a SRV item is removed because it is obsolete, we
must trigger a DNS resolution to be sure the hostname still resolves or
not. There is no other way to be the entry is still valid. And we cannot set
the server in RMAINT immediatly, because a DNS server may be inconsitent and
may stop to add some additionnal records.

The opposite is also true. If a valid ADD item is still attached to a SRV
item, any DNS resolution must be stopped. There is no reason to perform
extra resolution in this case.

This patch must be backported as far as 2.2.
2021-03-12 17:41:28 +01:00
Christopher Faulet
49531e8471 BUG/MINOR; resolvers: Ignore DNS resolution for expired SRV item
If no ADD item is found for a SRV item in a SRV response, a DNS resolution
is triggered. When it succeeds, we must be sure the SRV item is still
alive. Otherwise the DNS resolution must be ignored.

This patch depends on the commit "MINOR: resolvers: Move last_seen time of
an ADD into its corresponding SRV item". Both must be backported as far as
2.2.
2021-03-12 17:41:28 +01:00
Baptiste Assmann
6a8d11dc80 MINOR: resolvers: new function find_srvrq_answer_record()
This function search for a SRV answer item associated to a requester
whose type is server.
This is mainly useful to "link" a server to its SRV record when no
additional record were found to configure the IP address.

This patch is required by a bug fix.
2021-03-12 17:41:28 +01:00
Christopher Faulet
77f860699c BUG/MEDIUM: resolvers: Fix the loop looking for an existing ADD item
For each ADD item found in a SRV response, we try to find a corresponding
ADD item already attached to an existing SRV item. If found, the ADD
last_seen time is updated, otherwise we try to find a SRV item with no ADD
to attached the new one.

However, the loop is buggy. Instead of comparing 2 ADD items, it compares
the new ADD item with the SRV item. Because of this bug, we are unable to
renew last_seen time of existing ADD.

This patch must be backported as far as 2.2.
2021-03-12 17:41:24 +01:00
Christopher Faulet
ab177ac1f3 BUG/MEDIUM: resolvers: Don't set an address-less server as UP
when a server status is updated based on a SRV item, it is always set to UP,
regardless it has an IP address defined or not. For instance, if only a SRV
item is received, with no additional record, only the server hostname is
defined. We must wait to have an IP address to set the server as UP.

This patch must be backported as far as 2.2.
2021-03-12 16:43:37 +01:00
Christopher Faulet
bca680ba90 BUG/MINOR: resolvers: Unlink DNS resolution to set RMAINT on SRV resolution
When a server is set in RMAINT becaues of a SRV resolution failure, the
server DNS resolution, if any, must be unlink first. It is mandatory to
handle the change in the context of a SRV resolution.

This patch must be backported as far as 2.2.
2021-03-12 16:43:37 +01:00
Christopher Faulet
5130c21fbb BUG/MINOR: resolvers: Reset server address on DNS error only on status change
When a DNS resolution error is detected, in snr_resolution_error_cb(), the
server address must be reset only if the server status has changed. It this
case, it means the server is set to RMAINT. Thus the server address may by
reset.

This patch fixes a bug introduced by commit d127ffa9f ("BUG/MEDIUM:
resolvers: Reset address for unresolved servers"). It must be backported as
far as 2.0.
2021-03-12 16:43:37 +01:00
Christopher Faulet
bd0227c109 BUG/MINOR: resolvers: Consider server to have no IP on DNS resolution error
When an error is received for a DNS resolution, for instance a NXDOMAIN
error, the server must be considered to have no address when its status is
updated, not the opposite.

Concretly, because this parameter is not used on error path in
snr_update_srv_status(), there is no impact.

This patch must be backported as far as 1.8.
2021-03-12 16:43:37 +01:00
Christopher Faulet
5037c06d91 Revert "BUG/MINOR: resolvers: Only renew TTL for SRV records with an additional record"
This reverts commit a331a1e8eb.

This commit fixes a real bug, but it also reveals some hidden bugs, mostly
because of some design issues. Thus, in itself, it create more problem than
it solves. So revert it for now. All known bugs will be addressed in next
commits.

This patch should be backported as far as 2.2.
2021-03-12 16:43:37 +01:00
Willy Tarreau
736adef511 BUG/MINOR: cfgparse/server: increment the extra keyword counter one at a time
This was introduced in previous commit 49c2b45c1 ("MINOR: cfgparse/server:
try to fix spelling mistakes on server lines"), the loop was changed but
the increment left. No backport is needed.
2021-03-12 14:47:10 +01:00
Willy Tarreau
db67b0ed79 MINOR: tcp-rules: suggest approaching action names on mismatch
This adds support for action_suggest() in tcp-request and tcp-response
rules so as to propose the closest match in case of misspelling.
2021-03-12 14:13:21 +01:00
Willy Tarreau
49bf7beb14 MINOR: http-rules: suggest approaching action names on mismatch
This adds support for action_suggest() in http-request, http-response
and http-after-response rulesets. For example:

   parsing [/dev/stdin:2]: 'http-request' expects (...), but got 'del-hdr'. Did you mean 'del-header' maybe ?
2021-03-12 14:13:21 +01:00
Willy Tarreau
99eb2cc1cc MINOR: actions: add a function to suggest an action ressembling a given word
action_suggest() will return a pointer to an action whose keyword more or
less ressembles the passed argument. It also accepts to be more tolerant
against prefixes (since actions taking arguments are handled as prefixes).
This will be used to suggest approaching words.
2021-03-12 14:13:21 +01:00
Willy Tarreau
433b05fa64 MINOR: cfgparse/bind: suggest correct spelling for unknown bind keywords
Just like with the server keywords, now's the turn of "bind" keywords.
The difference is that 100% of the bind keywords are registered, thus
we do not need the list of extra keywords.

There are multiple bind line parsers today, all were updated:
  - peers
  - log
  - dgram-bind
  - cli

$ printf "listen f\nbind :8000 tcut\n" | ./haproxy -c -f /dev/stdin
[NOTICE] 070/101358 (25146) : haproxy version is 2.4-dev11-7b8787-26
[NOTICE] 070/101358 (25146) : path to executable is ./haproxy
[ALERT] 070/101358 (25146) : parsing [/dev/stdin:2] : 'bind :8000' unknown keyword 'tcut'; did you mean 'tcp-ut' maybe ?
[ALERT] 070/101358 (25146) : Error(s) found in configuration file : /dev/stdin
[ALERT] 070/101358 (25146) : Fatal errors found in configuration.
2021-03-12 14:13:21 +01:00
Willy Tarreau
49c2b45c1d MINOR: cfgparse/server: try to fix spelling mistakes on server lines
Let's apply the fuzzy match to server keywords so that we can avoid
dumping the huge list of supported keywords each time there is a spelling
mistake, and suggest proper spelling instead:

  $ printf "listen f\nserver s 0 sendpx-v2\n" | ./haproxy -c -f /dev/stdin
  [NOTICE] 070/095718 (24152) : haproxy version is 2.4-dev11-caa6e3-25
  [NOTICE] 070/095718 (24152) : path to executable is ./haproxy
  [ALERT] 070/095718 (24152) : parsing [/dev/stdin:2] : 'server s' unknown keyword 'sendpx-v2'; did you mean 'send-proxy-v2' maybe ?
  [ALERT] 070/095718 (24152) : Error(s) found in configuration file : /dev/stdin
  [ALERT] 070/095718 (24152) : Fatal errors found in configuration.
2021-03-12 14:13:21 +01:00
Willy Tarreau
a0e8eb8caa MINOR: cfgparse: suggest correct spelling for unknown words in global section
The global section also knows a large number of keywords that are not
referenced in any list, so this needed them to be specifically listed.
It becomes particularly handy now because some tunables are never easy
to remember, but now it works remarkably well:

  $ printf "global\nsched.queue_depth\n" | ./haproxy -c -f /dev/stdin
  [NOTICE] 070/093007 (23457) : haproxy version is 2.4-dev11-dd8ee5-24
  [NOTICE] 070/093007 (23457) : path to executable is ./haproxy
  [ALERT] 070/093007 (23457) : parsing [/dev/stdin:2] : unknown keyword 'sched.queue_depth' in 'global' section; did you mean 'tune.runqueue-depth' maybe ?
  [ALERT] 070/093007 (23457) : Error(s) found in configuration file : /dev/stdin
  [ALERT] 070/093007 (23457) : Fatal errors found in configuration.
2021-03-12 14:13:21 +01:00
Willy Tarreau
c0ff679481 MINOR: cfgparse: suggest correct spelling for unknown words in proxy sections
Let's start by the largest keyword list, the listeners. Many keywords were
still not part of a list, so a common_kw_list array was added to list the
not enumerated ones. Now for example, typing "tmout" properly suggests
"timeout":

  $ printf "frontend f\ntmout client 10s\n" | ./haproxy -c -f /dev/stdin
  [NOTICE] 070/091355 (22545) : haproxy version is 2.4-dev11-3b728a-21
  [NOTICE] 070/091355 (22545) : path to executable is ./haproxy
  [ALERT] 070/091355 (22545) : parsing [/dev/stdin:2] : unknown keyword 'tmout' in 'frontend' section; did you mean 'timeout' maybe ?
  [ALERT] 070/091355 (22545) : Error(s) found in configuration file : /dev/stdin
  [ALERT] 070/091355 (22545) : Fatal errors found in configuration.
2021-03-12 14:13:21 +01:00
Willy Tarreau
e2afcc4509 MINOR: cfgparse: add cfg_find_best_match() to suggest an existing word
Instead of just reporting "unknown keyword", let's provide a function which
will look through a list of registered keywords for a similar-looking word
to the one that wasn't matched. This will help callers suggest correct
spelling. Also, given that a large part of the config parser still relies
on a long chain of strcmp(), we'll need to be able to pass extra candidates.
Thus the function supports an optional extra list for this purpose.
2021-03-12 14:13:21 +01:00
Willy Tarreau
ba2c4459a5 MINOR: tools: add simple word fingerprinting to find similar-looking words
This introduces two functions, one which creates a fingerprint of a word,
and one which computes a distance between two words fingerprints. The
fingerprint is made by counting the transitions between one character and
another one. Here we consider the 26 alphabetic letters regardless of
their case, then any digit as a digit, and anything else as "other". We
also consider the first and last locations as transitions from begin to
first char, and last char to end. The distance is simply the sum of the
squares of the differences between two fingerprints. This way, doubling/
missing a letter has the same cost, however some repeated transitions
such as "e"->"r" like in "server" are very unlikely to match against
situations where they do not exist. This is a naive approach but it seems
to work sufficiently well for now. It may be refined in the future if
needed.
2021-03-12 14:13:21 +01:00
Willy Tarreau
25809999fe CLEANUP: http-rules: remove the unexpected comma before the list of action keywords
The error message for http-request and http-response starts with a comma
that very likely is a leftover from a previous list construct. Let's remove
it: "'http-request' expects , 'wait-for-handshake', 'use-service' ...".
2021-03-12 14:13:20 +01:00
Willy Tarreau
3d1d178933 CLEANUP: vars: make the error message clearer on missing arguments for set-var
The error message after "http-response set-var" isn't very clear:

  [ALERT] 070/115043 (30526) : parsing [/dev/stdin:2] : error detected in proxy 'f' while parsing 'http-response set-var' rule : invalid variable 'set-var'. Expects 'set-var(<var-name>)' or 'unset-var(<var-name>)'.

Let's change it to this instead:

  [ALERT] 070/115608 (30799) : parsing [/dev/stdin:2] : error detected in proxy 'f' while parsing 'http-response set-var' rule : invalid or incomplete action 'set-var'. Expects 'set-var(<var-name>)' or 'unset-var(<var-name>)'.

With a wrong action name, it also works better (it's handled as a prefix
due to the opening parenthesis):

  [ALERT] 070/115608 (30799) : parsing [/dev/stdin:2] : error detected in proxy 'f' while parsing 'http-response set-varxxx' rule : invalid or incomplete action 'set-varxxx'. Expects 'set-var(<var-name>)' or 'unset-var(<var-name>)'.
2021-03-12 14:13:20 +01:00
Willy Tarreau
72d012fbd9 CLEANUP: tcp-rules: add missing actions in the tcp-request error message
The tcp-request error message only mentions "accept", "reject" and
track-sc*, but there are a few other ones that were missing, so let's
add them.

This could be backported, though it's not likely that it will help anyone
with an existing config.
2021-03-12 14:13:20 +01:00
Willy Tarreau
47a30c456c BUG/MINOR: server-state: use the argument, not the global state
The refactoring in commit 131b07be3 ("MEDIUM: server: Refactor
apply_server_state() to make it more readable") also had a copy-paste
error resulting in using global.server_state_file instead of the
function's argument, which easily crashes with a conf having a
state file in a backend and no global state file.

In addition, let's simplify the code and get rid of strcpy() which
almost certainly will break the build on OpenBSD.

This was introduced in 2.4-dev10, no backport is needed.
2021-03-12 14:13:07 +01:00
Willy Tarreau
6d4173e622 BUG/MINOR: server-state: properly handle the case where the base is not set
The refactoring in commit 131b07be3 ("MEDIUM: server: Refactor
apply_server_state() to make it more readable") made the global
server_state_base be dereferenced before being checked, resulting
in a crash on certain files.

This happened in 2.4-dev10, no backport is needed.
2021-03-12 13:57:19 +01:00
Christopher Faulet
cd03be73d5 BUG/MINOR: tcpcheck: Fix double free on error path when parsing tcp/http-check
When a "tcp-check" or a "http-check" rule is parsed, we try to get the
previous rule in the ruleset to get its index. We must take care to reset
the pointer on this rule in case an error is triggered later on the
parsing. Otherwise, the same rule may be released twice. For instance, it
happens with such line :

    http-check meth GET uri / ## note there is no "send" parameter

This patch must be backported as far as 2.2.
2021-03-12 13:17:46 +01:00
Christopher Faulet
24ec943427 BUG/MINOR: tcpcheck: Update .health threshold of agent inside an agent-check
If an agent-check is configured for a server, When the response is parsed,
the .health threshold of the agent must be updated on up/down/stopped/fail
command and not the threshold of the health-check. Otherwise, the
agent-check will compete with the health-check and may mark a DOWN server as
UP.

This patch should fix the issue #1176. It must be backported as far as 2.2.
2021-03-12 09:25:45 +01:00
Christopher Faulet
5647fbacdf BUG/MEDIUM: filters: Set CF_FL_ANALYZE on channels when filters are attached
CF_FL_ANALYZE flag is used to know a channel is filtered. It is important to
synchronize request and response channels when the filtering ends.

However, it is possible to call all request analyzers before starting the
filtering on the response channel. This means flt_end_analyze() may be
called for the request channel before flt_start_analyze() on the response
channel. Thus because CF_FL_ANALYZE flag is not set on the response channel,
we consider the filtering is finished on both sides. The consequence is that
flt_end_analyze() is not called for the response and backend filters are
unregistered before their execution on the response channel.

It is possible to encounter this bug on TCP frontend or CONNECT request on
HTTP frontend if the client shutdown is reveiced with the first read.

To fix this bug, CF_FL_ANALYZE is set when filters are attached to the
stream. It means, on the request channel when the stream is created, in
flt_stream_start(). And on both channels when the backend is set, in
flt_set_stream_backend().

This patch must be backported as far as 1.7.
2021-03-12 09:25:45 +01:00
Emeric Brun
362d25e507 BUG/MEDIUM: stick-tables: fix ref counter in table entry using multiple http tracksc.
Setting multiple http-request track-scX rules generates entries
which never expires.

If there was already an entry registered by a previous http rule
'stream_track_stkctr(&s->stkctr[rule->action], t, ts)' didn't
register the new 'ts' into the stkctr. And function is left
with no reference on 'ts' whereas refcount had been increased
by the '_get_entry'

The patch applies the same policy as the one showed on tcp track
rules and if there is successive rules the track counter keep the
first entry registered in the counter and nothing more is computed.

After validation this should be backported in all versions.
2021-03-11 14:14:44 +01:00
Willy Tarreau
060a761248 OPTIM: task: automatically adjust the default runqueue-depth to the threads
The recent default runqueue size reduction appeared to have significantly
lowered performance on low-thread count configs. Testing various values
runqueue values on different workloads under thread counts ranging from
1 to 64, it appeared that lower values are more optimal for high thread
counts and conversely. It could even be drawn that the optimal value for
various workloads sits around 280/sqrt(nbthread), and probably has to do
with both the L3 cache usage and how to optimally interlace the threads'
activity to minimize contention. This is much easier to optimally
configure, so let's do this by default now.
2021-03-10 11:15:34 +01:00
Willy Tarreau
1691ba3693 MINOR: task: give the scheduler a bit more flexibility in the runqueue size
Instead of setting a hard-limit on runqueue-depth and keeping it short
to maintain fairness, let's allow the scheduler to automatically cut
the existing one in two equal halves if its size is between the configured
size and its double. This will allow to increase the default value while
keeping a low latency.
2021-03-10 11:15:34 +01:00
Willy Tarreau
4c48edba4f BUG/MEDIUM: ssl: properly remove the TASK_HEAVY flag at end of handshake
Emeric found that SSL+keepalive traffic had dropped quite a bit in the
recent changes, which could be bisected to recent commit 9205ab31d
("MINOR: ssl: mark the SSL handshake tasklet as heavy"). Indeed, a
first incarnation of this commit made use of the TASK_SELF_WAKING
flag but the last version directly used TASK_HEAVY, but it would still
continue to remove the already absent TASK_SELF_WAKING one instead of
TASK_HEAVY. As such, the SSL traffic remained processed with low
granularity.

No backport is needed as this is only 2.4.
2021-03-09 17:58:02 +01:00
Willy Tarreau
5a1c7280a9 CLEANUP: config: also address the cfg_keyword API change in the compression code
The tests were made on slz and the zlib parsers for memlevel and windowsize
managed to escape the change made by commit 018251667 ("CLEANUP: config: make
the cfg_keyword parsers take a const for the defproxy"). This is now fixed.
2021-03-09 16:57:08 +01:00
Willy Tarreau
e89fae3a4e CLEANUP: stream: rename a few remaining occurrences of "stream *sess"
These are some leftovers from the ancient code where they were still
called sessions, but these areas in the code remain confusing due to
this naming. They were now called "strm" which will not even affect
indenting nor alignment.
2021-03-09 15:44:33 +01:00
William Lallemand
36119de182 BUG/MEDIUM: session: NULL dereference possible when accessing the listener
When implementing a client applet, a NULL dereference was encountered on
the error path which increment the counters.

Indeed, the counters incremented are the one in the listener which does
not exist in the case of client applets, so in sess->listener->counters,
listener is NULL.

This patch fixes the access to the listener structure when accessing
from a sesssion, most of the access are the counters in error paths.

Must be backported as far as 1.8.
2021-03-09 12:51:42 +01:00
Willy Tarreau
018251667e CLEANUP: config: make the cfg_keyword parsers take a const for the defproxy
The default proxy was passed as a variable to all parsers instead of a
const, which is not without risk, especially when some timeout parsers used
to make some int pointers point to the default values for comparisons. We
want to be certain that none of these parsers will modify the defaults
sections by accident, so it's important to mark this proxy as const.

This patch touches all occurrences found (89).
2021-03-09 10:09:43 +01:00
Willy Tarreau
b7e0c633e8 BUILD: task: fix build at -O0 with threads disabled
grq_total was incremented when picking tasks from the global run queue,
but this variable was not defined with threads disabled, and the code
was optimized away at -O2. No backport is needed.
2021-03-09 10:01:01 +01:00
Tim Duesterhus
56c176a780 CLEANUP: connection: Consistently use struct ist to process all TLV types
Instead of directly poking around within the `struct tlv tlv_packet` the actual
value will be consumed using a `struct ist`.
2021-03-09 09:24:32 +01:00
Tim Duesterhus
615f81eb5a MINOR: connection: Use a struct ist to store proxy_authority
This makes the code cleaner, because proxy_authority can be handled like
proxy_unique_id.
2021-03-09 09:24:32 +01:00
Tim Duesterhus
002bd77a6e CLEANUP: connection: Use istptr / istlen for proxy_unique_id
Don't access the ist's fields directly, use the helper functions instead.
2021-03-09 09:24:32 +01:00
Ilya Shipitsin
d7a988c14a CLEANUP: assorted typo fixes in the code and comments
This is 19th iteration of typo fixes
2021-03-05 21:22:47 +01:00
Amaury Denoyelle
249f0562cf BUG/MINOR: backend: fix condition for reuse on mode HTTP
This commit is a fix/complement to the following one :
08d87b3f49
BUG/MEDIUM: backend: never reuse a connection for tcp mode

It fixes the check for the early insertion of backend connections in
the reuse lists if the backend mode is HTTP.

The impact of this bug seems limited because :
- in tcp mode, no insertion is done in the avail list as mux_pt does not
  support multiple streams.
- in http mode, muxes are also responsible to insert backend connections
  in lists in their detach functions. Prior to this fix the reuse rate
  could be slightly inferior.

It can be backported to 2.3.
2021-03-05 15:44:51 +01:00
Amaury Denoyelle
d7faa3d6e9 MINOR: backend: add a BUG_ON if conn mux NULL in connect_server
Currently, there seems to be no way to have the transport layer ready
but not the mux in the function connect_server. Add a BUG_ON to report
if this implicit condition is not true anymore.

This should fix coverity report from github issue #1120.
2021-03-05 15:27:41 +01:00
Willy Tarreau
d4e78d873c MINOR: server: move actconns to the per-thread structure
The actconns list creates massive contention on low server counts because
it's in fact a list of streams using a server, all threads compete on the
list's head and it's still possible to see some watchdog panics on 48
threads under extreme contention with 47 threads trying to add and one
thread trying to delete.

Moving this list per thread is trivial because it's only used by
srv_shutdown_streams(), which simply required to iterate over the list.

The field was renamed to "streams" as it's really a list of streams
rather than a list of connections.
2021-03-05 15:00:24 +01:00
Willy Tarreau
430bf4a483 MINOR: server: allocate a per-thread struct for the per-thread connections stuff
There are multiple per-thread lists in the listeners, which isn't the
most efficient in terms of cache, and doesn't easily allow to store all
the per-thread stuff.

Now we introduce an srv_per_thread structure which the servers will have an
array of, and place the idle/safe/avail conns tree heads into. Overall this
was a fairly mechanical change, and the array is now always initialized for
all servers since we'll put more stuff there. It's worth noting that the Lua
code still has to deal with its own deinit by itself despite being in a
global list, because its server is not dynamically allocated.
2021-03-05 15:00:24 +01:00
Willy Tarreau
4cdac166e0 MINOR: cfgparse: finish to set up servers outside of the proxy setup loop
Till now servers were only initialized as part of the proxy setup loop,
which doesn't cover peers, tcp log, dns, lua etc. Let's move this part
out of this loop and instead iterate over all registered servers. This
way we're certain to visit them all.

The patch looks big but it's just a move of a large block with the
corresponding reindent (as can be checked with diff -b). It relies
on the two previous ones ("MINOR: server: add a global list of all
known servers and" and "CLEANUP: lua: set a dummy file name and line
number on the dummy servers").
2021-03-05 15:00:24 +01:00
Willy Tarreau
198e92a8e5 MINOR: server: add a global list of all known servers
It's a real pain not to have access to the list of all registered servers,
because whenever there is a need to late adjust their configuration, only
those attached to regular proxies are seen, but not the peers, lua, logs
nor DNS.

What this patch does is that new_server() will automatically add the newly
created server to a global list, and it does so as well for the 1 or 2
statically allocated servers created for Lua. This way it will be possible
to iterate over all of them.
2021-03-05 15:00:24 +01:00
Willy Tarreau
0f143afe1b CLEANUP: lua: set a dummy file name and line number on the dummy servers
The "socket_tcp" and "socket_ssl" servers had no config file name nor
line number, but this is sometimes annoying during debugging or later
in error messages, while all other places using new_server() or
parse_server() make sure to have a valid file:line set. Let's set
something to address this.
2021-03-05 15:00:24 +01:00
Willy Tarreau
5b5974104f CLEANUP: sockpair: silence a coverity check about fcntl()
This is about coverity complaining that we didn't check the fcntl call
which can't fail, let's consume it. This is issue #1158.
2021-03-05 14:33:13 +01:00
Willy Tarreau
4149168255 MEDIUM: ssl: implement xprt_set_used and xprt_set_idle to relax context checks
Currently the SSL layer checks the validity of its tasklet's context just
in case it would have been stolen, had the connection been idle. Now it
will be able to be notified by the mux when this situation happens so as
not to have to grab the idle connection lock on each pass. This reuses the
TASK_F_USR1 flag just as the muxes do.
2021-03-05 08:30:08 +01:00
Willy Tarreau
4f8cd4397f MINOR: xprt: add new xprt_set_idle and xprt_set_used methods
These functions are used on the mux layer to indicate that the connection
is becoming idle and that the xprt ought to be careful before checking the
context or that it's not idle anymore and that the context is safe. The
purpose is to allow a mux which is going to release a connection to tell
the xprt to be careful when touching it. At the moment, the xprt are
always careful and that's costly so we want to have the ability to relax
this a bit.

No xprt layer uses this yet.
2021-03-05 08:30:08 +01:00
Willy Tarreau
e388f2fbca MEDIUM: muxes: mark idle conns tasklets with TASK_F_USR1
The muxes are touching the idle_conns_lock all the time now because
they need to be careful that no other thread has stolen their tasklet's
context.

This patch changes this a little bit by setting the TASK_F_USR1 flag on
the tasklet before marking a connection idle, and removing it once it's
not idle anymore. Thanks to this we have the guarantee that a tasklet
without this flag cannot be present in an idle list and does not need
to go through this costly lock. This is especially true for front
connections.
2021-03-05 08:30:08 +01:00
Willy Tarreau
6fa8bcdc78 MINOR: task: add an application specific flag to the state: TASK_F_USR1
This flag will be usable by any application. It will be preserved across
wakeups so the application can use it to do various stuff. Some I/O
handlers will soon benefit from this.
2021-03-05 08:30:08 +01:00
Willy Tarreau
144f84a09d MEDIUM: task: extend the state field to 32 bits
It's been too short for quite a while now and is now full. It's still
time to extend it to 32-bits since we have room for this without
wasting any space, so we now gained 16 new bits for future flags.

The values were not reassigned just in case there would be a few
hidden u16 or short somewhere in which these flags are placed (as
it used to be the case with stream->pending_events).

The patch is tagged MEDIUM because this required to update the task's
process() prototype to use an int instead of a short, that's quite a
bunch of places.
2021-03-05 08:30:08 +01:00
Willy Tarreau
db4e238938 MINOR: task: stop abusing the nice field to detect a tasklet
It's cleaner to use a flag from the task's state to detect a tasklet
and it's even cheaper. One of the best benefits is that this will
allow to get the nice field out of the common part since the tasklet
doesn't need it anymore. This commit uses the last task bit available
but that's temporary as the purpose of the change is to extend this.
2021-03-05 08:30:08 +01:00
Ubuntu
1adaddb494 OPTIM: lb-random: use a cheaper PRNG to pick a server
The PRNG used by the "random" LB algorithm was the central one which tries
hard to produce "correct" (i.e. hardly predictable) values suitable for use
in UUIDs or cookies. It's much too expensive for pure load balancing where
a cheaper thread-local PRNG is sufficient, and the current PRNG is part of
the hot places when running with many threads.

Let's switch to the stastistical PRNG instead, it's thread-local, very
fast, and with a period of (2^32)-1 which is more than enough to decide
on a server.
2021-03-05 08:30:08 +01:00
Willy Tarreau
06e69b556c REORG: tools: promote the debug PRNG to more general use as a statistical one
We frequently need to access a simple and fast PRNG for statistical
purposes. The debug_prng() function did exactly this using a xorshift
generator but its use was limited to debug only. Let's move this to
tools.h and tools.c to make it accessible everywhere. Since it needs to
be fast, its state is thread-local. An initialization function starts a
different initial value for each thread for better distribution.
2021-03-05 08:30:08 +01:00
Ubuntu
b1adf03df9 MEDIUM: backend: use a trylock when trying to grab an idle connection
In conn_backend_get() we can cause some extreme contention due to the
idle_conns_lock. Indeed, even though it's per-thread, it still causes
high contention when running with many threads. The reason is that all
threads which do not have any idle connections are quickly skipped,
till the point where there are still some, so the first reaching that
point will grab the lock and the other ones wait behind. From this
point, all threads are synchronized waiting on the same lock, and
will follow the leader in small jumps, all hindering each other.

Here instead of doing this we're using a trylock. This way when a thread
is already checking a list, other ones will continue to next thread. In
the worst case, a high contention will lead to a few new connections to
be set up, but this may actually be what is required to avoid contention
in the first place. With this change, the contention has mostly
disappeared on this lock (it's still present in muxes and transport
layers due to the takeover).

Surprisingly, checking for emptiness of the tree root before taking
the lock didn't address any contention.

A few improvements are still possible and desirable here. The first
one would be to avoid seeing all threads jump to the next one. We
could have each thread use a different prime number as the increment
so as to spread them across the entire table instead of keeping them
synchronized. The second one is that the lock in the muck layers
shouldn't be needed to check for the tasklet's context availability.
2021-03-05 08:30:08 +01:00
Willy Tarreau
2f67e54dca MINOR: stream: use ABORT_NOW() and not abort() in stream_dump_and_crash()
Using abort() occasionally results in unexploitable core due to issues
rewinding the stack. Let's use ABORT_NOW() which in addition to crashing
much closer to the call point also has the benefit of showing the call
trace.
2021-03-05 08:30:08 +01:00
Willy Tarreau
0bae075928 MEDIUM: pools: add CONFIG_HAP_NO_GLOBAL_POOLS and CONFIG_HAP_GLOBAL_POOLS
We've reached a point where the global pools represent a significant
bottleneck with threads. On a 64-core machine, the performance was
divided by 8 between 32 and 64 H2 connections only because there were
not enough entries in the local caches to avoid picking from the global
pools, and the contention on the list there was very high. It becomes
obvious that we need to have an array of lists, but that will require
more changes.

In parallel, standard memory allocators have improved, with tcmalloc
and jemalloc finding their ways through mainstream systems, and glibc
having upgraded to a thread-aware ptmalloc variant, keeping this level
of contention here isn't justified anymore when we have both the local
per-thread pool caches and a fast process-wide allocator.

For these reasons, this patch introduces a new compile time setting
CONFIG_HAP_NO_GLOBAL_POOLS which is set by default when threads are
enabled with thread local pool caches, and we know we have a fast
thread-aware memory allocator (currently set for glibc>=2.26). In this
case we entirely bypass the global pool and directly use the standard
memory allocator when missing objects from the local pools. It is also
possible to force it at compile time when a good allocator is used with
another setup.

It is still possible to re-enable the global pools using
CONFIG_HAP_GLOBAL_POOLS, if a corner case is discovered regarding the
operating system's default allocator, or when building with a recent
libc but a different allocator which provides other benefits but does
not scale well with threads.
2021-03-05 08:30:08 +01:00
Willy Tarreau
566cebc1fc BUG/MINOR: ssl: don't truncate the file descriptor to 16 bits in debug mode
Errors reported by ssl_sock_dump_errors() to stderr would only report the
16 lower bits of the file descriptor because it used to be casted to ushort.
This can be backported to all versions but has really no importance in
practice since this is never seen.
2021-03-05 08:30:08 +01:00
Tim Duesterhus
1568355afd CLEANUP: Replace for loop with only a condition by while
Refactoring performed with the following Coccinelle patch:

    @@
    expression e;
    statement S;
    @@

    - for (;e;)
    + while (e)
      S
2021-03-05 08:28:53 +01:00
Tim Duesterhus
dcf753aabe CLEANUP: Use the ist() macro whenever possible
Refactoring performed with the following Coccinelle patch:

    @@
    char *s;
    @@

    (
    - ist2(s, strlen(s))
    + ist(s)
    |
    - ist2(strdup(s), strlen(s))
    + ist(strdup(s))
    )

Note that this replacement is safe even in the strdup() case, because `ist()`
will not call `strlen()` on a `NULL` pointer. Instead is inserts a length of
`0`, effectively resulting in `IST_NULL`.
2021-03-05 08:28:53 +01:00
Christopher Faulet
1e711beb51 CLEANUP: dns: Remove useless test on ns->dgram in dns_connect_nameserver()
When dns_connect_nameserver() is called, the nameserver has always a dgram
field properly defined. The caller, dns_send_nameserver(), already performed
the appropriate verification.
2021-03-04 16:58:36 +01:00
Christopher Faulet
1a1b674c2c CLEANUP: dns: Use DISGUISE() on a never-failing ring_attach() call
When a DNS session is created, the call to ring_attach() never fails. The
ring is freshly initialized and there is other watcher on it. Thus, the call
always succeeds.

Instead of catching an error that must never happen, we use the DISGUISE()
macro to make static analyzers happy.
2021-03-04 16:53:28 +01:00
Christopher Faulet
6f69110191 BUG/MINOR: server-state: Don't load server-state file for disabled backends
Recent changes on the server-state file loading have introduced a
regression. HAproxy crashes if a backend with no server-state file is
disabled in the configuration. Indeed, configuration of such backends is not
finalized. Thus many fields are not defined.

To fix the bug, disabled backends must be ignored. In addition a BUG_ON()
has been added to verify the proxy mode regarding the server-state file. It
must be specified (none, global or local) for enabled backends.

No backport needed.
2021-03-04 16:49:10 +01:00
Christopher Faulet
2ec4e3c1ac BUG/MINOR: hlua: Don't strip last non-LWS char in hlua_pushstrippedstring()
hlua_pushstrippedstring() function strips leading and trailing LWS
characters. But the result length it too short by 1 byte. Thus the last
non-LWS character is stripped. Note that a string containing only LWS
characters resulting to a stipped string with an invalid length (-1). This
leads to a lua runtime error.

This bug was reported in the issue #1155. It must be backported as far as
1.7.
2021-03-03 19:48:12 +01:00
Amaury Denoyelle
8ede3db080 MINOR: backend: handle reuse for conns with no server as target
If dispatch mode or transparent backend is used, the backend connection
target is a proxy instead of a server. In these cases, the reuse of
backend connections is not consistent.

With the default behavior, no reuse is done and every new request uses a
new connection. However, if http-reuse is set to never, the connection
are stored by the mux in the session and can be reused for future
requests in the same session.

As no server is used for these connections, no reuse can be made outside
of the session, similarly to http-reuse never mode. A different
http-reuse config value should not have an impact. To achieve this, mark
these connections as private to have a defined behavior.

For this feature to properly work, the connection hash has been slightly
adjusted. The server pointer as an input as been replaced by a generic
target pointer to refer to the server or proxy instance. The hash is
always calculated on connect_server even if the connection target is not
a server. This also requires to allocate the connection hash node for
every backend connections, not just the one with a server target.
2021-03-03 11:31:19 +01:00
Amaury Denoyelle
68967e595b BUG/MINOR: backend: free allocated bind_addr if reuse conn
Fix a leak in connect_server which happens when a connection is reused
and a bind_addr was allocated because transparent mode is active. The
connection has already an allocated bind_addr so free the newly
allocated one.

No backport needed.
2021-03-03 11:28:02 +01:00
Amaury Denoyelle
603657835f CLEANUP: backend: fix a wrong comment
missing 'not' when skipping reuse if proxy mode not HTTP
2021-03-03 11:28:02 +01:00
Tim Duesterhus
7b5777d9b4 CLEANUP: Use isttest(const struct ist) whenever possible
Refactoring performed with the following Coccinelle patch:

    @@
    struct ist i;
    @@

    - i.ptr != NULL
    + isttest(i)
2021-03-03 05:07:10 +01:00
Tim Duesterhus
154374cbc8 CLEANUP: Use istadv(const struct ist, const size_t) whenever possible
Refactoring performed with the following Coccinelle patch:

    @@
    struct ist i;
    expression e;
    @@

    - i.ptr += e;
    - i.len -= e;
    + i = istadv(i, e);
2021-03-03 05:07:10 +01:00
Tim Duesterhus
9f75ed114f CLEANUP: Reapply the ist2() replacement patch
One location was not matched due to a typo. Reapply the patch for consistency.

see 92c696e663
see a3298023b0
2021-03-03 05:07:10 +01:00
Tim Duesterhus
a3298023b0 BUG/MINOR: mux-h2: Fix typo in scheme adjustment
That comma should've been a semicolon. Fortunately, as it is now there
is no impact thanks to operators precedence, and all expressions are
properly evaluated. But this is troubling and the risk is high to
turn it into an effective bug with a minor change.

Introduced in b8ce8905cf which first
appeared in 2.1-dev3. This fix must be backported to 2.1+.
2021-03-02 14:13:57 +01:00
Frédéric Lécaille
f57c64fc06 BUILD: proxy: Missing header inclusion for quic_transport_params_init()
Since this commit:
144289b45 ("REORG: move init_default_instance() to proxy.c and pass it the defproxy pointer")
as quic_transport_params_init() has been moved from cfgparse.c to proxy.c this
latter source file must include xprt_quic.h header.

Should fix #1153 issue.
2021-03-02 09:45:49 +01:00
Tim Duesterhus
68a088d851 CLEANUP: Use IST_NULL whenever possible
Refactoring performed with the following Coccinelle patch:

    @@
    @@

    - ist2(NULL, 0)
    + IST_NULL
2021-03-01 15:44:28 +01:00
Tim Duesterhus
92c696e663 CLEANUP: Use ist2(const void*, size_t) whenever possible
Refactoring performed with the following Coccinelle patch:

    @@
    struct ist i;
    expression p, l;
    @@

    - i.ptr = p;
    - i.len = l;
    + i = ist2(p, l);
2021-03-01 15:44:20 +01:00
Christopher Faulet
9e647e5af7 BUG/MEDIUM: spoe: Kill applets if there are pending connections and nbthread > 1
When the processing stage is finished for a SPOE applet, before returning it
into the idle list, we check if the assigned server appears as full or if
there are some pending connections on the backend or the assigned server. If
yes, it means we reach a maxconn and we close the applet to free a
slot. Otherwise, the applet can be reused. This test is only performed if
there are more than one thread.

It is important to close SPOE applets when there are pending connections for
multithreaded instances because connections with the SPOE agents are
persistent and local to a thread (applets are local to a thread). If a
maxconn is configured, some threads may take all available slots for a
while, leaving remaining threads without any free slot to process SPOE
messages. It is especially true if the maxconn is low.

This patch should fix the issue #705. It must be backported as far as
1.8. However, the code in 1.8 is quite different, a test must be performed
to be sure it works well.
2021-03-01 15:10:19 +01:00
Christopher Faulet
ae3056157c BUG/MINOR: connection: Use the client's dst family for adressless servers
When the selected server has no address, the destination address of the
client is used. However, for now, only the address is set, not the
family. Thus depending on how the server is configured and the client's
destination address, the server address family may be wrong.

For instance, with such server :

   server srv 0.0.0.0:0

The server address family is AF_INET. The server connection will fail if a
client is asking for an IPv6 destination.

To fix the bug, we take care to set the rigth family, the family of the
client destination address.

This patch should fix the issue #202. It must be backported to all stable
versions.
2021-03-01 11:34:00 +01:00
Christopher Faulet
e01ca0fbc9 BUG/MINOR: tcp-act: Don't forget to set the original port for IPv4 set-dst rule
If an IPv4 is set via a TCP/HTTP set-dst rule, the original port must be
preserved or set to 0 if the previous family was neither AF_INET nor
AF_INET6. The first case is not an issue because the port remains the
same. But if the previous family was, for instance, AF_UNIX, the port is not
set to 0 and have an undefined value.

This patch must be backported as far as 1.7.
2021-03-01 11:28:54 +01:00
Ilya Shipitsin
0de36adb5c CLEANUP: assorted typo fixes in the code and comments
This is 18th iteration of typo fixes
2021-02-27 09:01:43 +01:00
Willy Tarreau
3bda3f422e CLEANUP: ssl: use realloc() instead of free()+malloc()
There was a free(ptr) followed by ptr=malloc(ptr, len), which is the
equivalent of ptr = realloc(ptr, len) but slower and less clean. Let's
replace this.
2021-02-26 21:27:33 +01:00
Willy Tarreau
e709e82173 CLEANUP: ssl: make ssl_sock_free_srv_ctx() zero the pointers after free
In ssl_sock_free_srv_ctx() there are some calls to free() which are not
followed by a zeroing of the pointers. For now this function is only used
during deinit but it could be used at run time in the near future, so
better secure this.
2021-02-26 21:23:06 +01:00
Willy Tarreau
01acf563a7 CLEANUP: ssl: remove a useless "if" before freeing an error message
Just an old "if (err) free(err)" that managed to escape cleanups.
2021-02-26 21:22:20 +01:00
Willy Tarreau
5b52b00393 CLEANUP: vars: always zero the pointers after a free()
In sample_store(), depending on the new sample types, the area pointer
was not always zeroed after being freed. Let's make sure it's always the
case to avoid the risk of dangling pointers being misused.
2021-02-26 21:21:21 +01:00
Willy Tarreau
35cd734356 CLEANUP: config: replace a few free() with ha_free()
A few occurrences of calls to free() to free a section name,
peers name or server name were using casts and didn't include
the trailing free, let's switch them to ha_free().
2021-02-26 21:21:21 +01:00
Willy Tarreau
61cfdf4fd8 CLEANUP: tree-wide: replace free(x);x=NULL with ha_free(&x)
This makes the code more readable and less prone to copy-paste errors.
In addition, it allows to place some __builtin_constant_p() predicates
to trigger a link-time error in case the compiler knows that the freed
area is constant. It will also produce compile-time error if trying to
free something that is not a regular pointer (e.g. a function).

The DEBUG_MEM_STATS macro now also defines an instance for ha_free()
so that all these calls can be checked.

178 occurrences were converted. The vast majority of them were handled
by the following Coccinelle script, some slightly refined to better deal
with "&*x" or with long lines:

  @ rule @
  expression E;
  @@
  - free(E);
  - E = NULL;
  + ha_free(&E);

It was verified that the resulting code is the same, more or less a
handful of cases where the compiler optimized slightly differently
the temporary variable that holds the copy of the pointer.

A non-negligible amount of {free(str);str=NULL;str_len=0;} are still
present in the config part (mostly header names in proxies). These
ones should also be cleaned for the same reasons, and probably be
turned into ist strings.
2021-02-26 21:21:09 +01:00
Christopher Faulet
29e9326f2f CLEANUP: hlua: Use net_addr structure internally to parse and compare addresses
hlua_addr structure may be replaced by net_addr structure to parse and
compare addresses. Both structures are similar.
2021-02-26 13:53:26 +01:00
Christopher Faulet
5d1def623a MEDIUM: http-ana: Add IPv6 support for forwardfor and orignialto options
A network may be specified to avoid header addition for "forwardfor" and
"orignialto" option via the "except" parameter. However, only IPv4
networks/addresses are supported. This patch adds the support of IPv6.

To do so, the net_addr structure is used to store the parameter value in the
proxy structure. And ipcmp2net() function is used to perform the comparison.

This patch should fix the issue #1145. It depends on the following commit:

  * c6ce0ab MINOR: tools: Add function to compare an address to a network address
  * 5587287 MINOR: tools: Add net_addr structure describing a network addess
2021-02-26 13:52:48 +01:00
Christopher Faulet
9553de7fec MINOR: tools: Add function to compare an address to a network address
ipcmp2net() function may be used to compare an addres (struct
sockaddr_storage) to a network address (struct net_addr). Among other
things, this function will be used to add support of IPv6 for "except"
parameter of "forwardfor" and "originalto" options.
2021-02-26 13:52:06 +01:00
Christopher Faulet
cccded98c7 BUG/MINOR: http-ana: Only consider dst address to process originalto option
When an except parameter is used for originalto option, only the destination
address must be evaluated. Especially, the address family of the destination
must be tested and not the source one.

This patch must be backported to all stable versions. However be careful,
depending the versions the code may be slightly different.
2021-02-26 13:32:14 +01:00
Willy Tarreau
76390dac06 MINOR: task: only limit TL_HEAVY tasks but not others
The preliminary approach to dealing with heavy tasks forced us to quit
the poller after meeting one. Now instead we process at most one per poll
loop and ignore the next ones, so that we get more bandwidth to process
all other classes.

Doing so further reduced the induced HTTP request latency at 100k req/s
under the stress of 1000 concurrent SSL handshakes in the following
proportions:

            |   default  | low-latency
   ---------+------------+--------------
    before  |   2.75 ms  |   2.0 ms
    after   |   1.38 ms  |   0.98 ms

In both cases, the latency is roughly halved. It's worth noting that
both values are now exactly 10 times better than in 2.4-dev9. Even the
percentiles have much improved. For 16 HTTP connections (1 per thread)
competing with 1000 SSL handshakes, we're seeing these long-tail
latencies (in milliseconds) :

              |  99.5%  |  99.9%  |  100%
   -----------+---------+---------+--------
   2.4-dev9   |  48.4   |  58.1   |  78.5
   previous   |   6.2   |  11.4   |  67.8
   this patch |   2.8   |   2.9   |   6.1

The task latency profiling report now shows this in default mode:
  $ socat - /tmp/sock1 <<< "show profiling"
  Per-task CPU profiling              : on      # set profiling tasks {on|auto|off}
  Tasks activity:
    function                      calls   cpu_tot   cpu_avg   lat_tot   lat_avg
    si_cs_io_cb                 3061966   2.224s    726.0ns   42.03s    13.72us
    h1_io_cb                    3061960   6.418s    2.096us   18.76m    367.6us
    process_stream              3059982   9.137s    2.985us   15.52m    304.3us
    ssl_sock_io_cb               602657   4.265m    424.7us   4.736h    28.29ms
    h1_timeout_task              202973      -         -      6.254s    30.81us
    accept_queue_process         135547   1.179s    8.699us   16.29s    120.1us
    srv_cleanup_toremove_conns       81   15.64ms   193.1us   30.87ms   381.1us
    task_run_applet                  10   758.7us   75.87us   51.77us   5.176us
    srv_cleanup_idle_conns            4   375.3us   93.83us   54.52us   13.63us

And this in low-latency mode, showing that both si_cs_io_cb() and process_stream()
have significantly benefitted from the improvement, with values 50 to 200 times
smaller than 2.4-dev9:
  $ socat - /tmp/sock1 <<< "show profiling"
  Per-task CPU profiling              : on      # set profiling tasks {on|auto|off}
  Tasks activity:
    function                      calls   cpu_tot   cpu_avg   lat_tot   lat_avg
    h1_io_cb                    6407006   11.86s    1.851us   31.14m    291.6us
    process_stream              6403890   18.40s    2.873us   2.134m    20.00us
    si_cs_io_cb                 6403866   4.139s    646.0ns   1.773m    16.61us
    ssl_sock_io_cb               894326   6.407m    429.9us   7.326h    29.49ms
    h1_timeout_task              301189      -         -      8.440s    28.02us
    accept_queue_process         211989   1.691s    7.977us   21.48s    101.3us
    srv_cleanup_toremove_conns      220   23.46ms   106.7us   65.61ms   298.2us
    task_run_applet                  16   1.219ms   76.17us   181.7us   11.36us
    srv_cleanup_idle_conns           12   713.3us   59.44us   168.4us   14.03us

The changes are slightly more invasive than previous ones and depend on
recent patches so they are not likely well suited for backporting.
2021-02-26 12:00:53 +01:00
Willy Tarreau
826fa87246 MINOR: task: place the heavy elements in TL_HEAVY
Instead of placing heavy tasklets into the TL_BULK queue, we now place
them into the TL_HEAVY one, which is assigned a default weight of ~1%
load at once. This way heavy tasks will not block TL_BULK anymore.
2021-02-26 12:00:53 +01:00
Willy Tarreau
401135cee6 MINOR: task: add one extra tasklet class: TL_HEAVY
This class will be used exclusively for heavy processing tasklets. It
will be cleaner than mixing them with the bulk ones. For now it's
allocated ~1% of the CPU bandwidth.

The largest part of the patch consists in re-arranging the fields in the
task_per_thread structure to preserve a clean alignment with one more
list head. Since we're now forced to increase the struct past a second
cache line, it now uses 4 cache lines (for easy multiplying) with the
first two ones being exclusively used by local operations and the third
one mostly by atomic operations. Interestingly, this better arrangement
causes less stress and reduced the response time by 8 microseconds at
1 million requests per second.
2021-02-26 12:00:53 +01:00
Eric Salama
6ac61e39c4 BUG/MINOR: ssl: potential null pointer dereference in ckchs_dup()
A potential null pointer dereference was reported with an old gcc
version (6.5)

    src/ssl_ckch.c: In function 'cli_parse_set_cert':
    src/ssl_ckch.c:844:7: error: potential null pointer dereference [-Werror=null-dereference]
      if (!ssl_sock_copy_cert_key_and_chain(src->ckch, dst->ckch))
	   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    src/ssl_ckch.c:844:7: error: potential null pointer dereference [-Werror=null-dereference]
    src/ssl_ckch.c: In function 'ckchs_dup':
    src/ssl_ckch.c:844:7: error: potential null pointer dereference [-Werror=null-dereference]
      if (!ssl_sock_copy_cert_key_and_chain(src->ckch, dst->ckch))
	   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    src/ssl_ckch.c:844:7: error: potential null pointer dereference [-Werror=null-dereference]

This could happen if ckch_store_new() fails to allocate memory and returns NULL.

This patch must be backported with 8f71298 since it was wrongly fixed and
the bug could happen.

Must be backported as far as 2.2.
2021-02-26 09:49:35 +01:00
Willy Tarreau
d8aa21a611 CLEANUP: server: rename srv_cleanup_{idle,toremove}_connections()
These function names are unbearably long, they don't even fit into the
screen in "show profiling", let's trim the "_connections" to "_conns",
which happens to match the name of the lists there.
2021-02-26 00:30:22 +01:00
Willy Tarreau
9205ab31d2 MINOR: ssl: mark the SSL handshake tasklet as heavy
There's a fairness issue between SSL and clear text. A full end-to-end
cleartext connection can require up to ~7.7 wakeups on average, plus 3.3
for the SSL tasklet, one of which is particularly expensive. So if we
accept to process many handshakes taking 1ms each, we significantly
increase the processing time of regular tasks just by adding an extra
delay between their calls. Ideally in order to be fair we should have a
1:18 call ratio, but this requires a bit more accounting. With very little
effort we can mark the SSL handshake tasklet as TASK_HEAVY until the
handshake completes, and remove it once done.

Doing so reduces from 14 to 3.0 ms the total response time experienced
by HTTP clients running in parallel to 1000 SSL clients doing full
handshakes in loops. Better, when tune.sched.low-latency is set to "on",
the latency further drops to 1.8 ms.

The tasks latency distribution explain pretty well what is happening:

Without the patch:
  $ socat - /tmp/sock1 <<< "show profiling"
  Per-task CPU profiling              : on      # set profiling tasks {on|auto|off}
  Tasks activity:
    function                      calls   cpu_tot   cpu_avg   lat_tot   lat_avg
    ssl_sock_io_cb              2785375   19.35m    416.9us   5.401h    6.980ms
    h1_io_cb                    1868949   9.853s    5.271us   4.829h    9.302ms
    process_stream              1864066   7.582s    4.067us   2.058h    3.974ms
    si_cs_io_cb                 1733808   1.932s    1.114us   26.83m    928.5us
    h1_timeout_task              935760      -         -      1.033h    3.975ms
    accept_queue_process         303606   4.627s    15.24us   16.65m    3.291ms
    srv_cleanup_toremove_connections452   64.31ms   142.3us   2.447s    5.415ms
    task_run_applet                  47   5.149ms   109.6us   57.09ms   1.215ms
    srv_cleanup_idle_connections     34   2.210ms   65.00us   87.49ms   2.573ms

With the patch:
  $ socat - /tmp/sock1 <<< "show profiling"
  Per-task CPU profiling              : on      # set profiling tasks {on|auto|off}
  Tasks activity:
    function                      calls   cpu_tot   cpu_avg   lat_tot   lat_avg
    ssl_sock_io_cb              3000365   21.08m    421.6us   20.30h    24.36ms
    h1_io_cb                    2031932   9.278s    4.565us   46.70m    1.379ms
    process_stream              2010682   7.391s    3.675us   22.83m    681.2us
    si_cs_io_cb                 1702070   1.571s    922.0ns   8.732m    307.8us
    h1_timeout_task             1009594      -         -      17.63m    1.048ms
    accept_queue_process         339595   4.792s    14.11us   3.714m    656.2us
    srv_cleanup_toremove_connections779   75.42ms   96.81us   438.3ms   562.6us
    srv_cleanup_idle_connections     48   2.498ms   52.05us   178.1us   3.709us
    task_run_applet                  17   1.738ms   102.3us   11.29ms   663.9us
    other                             1   947.8us   947.8us   202.6us   202.6us

  => h1_io_cb() and process_stream() are divided by 6 while ssl_sock_io_cb() is
     multipled by 4

And with low-latency on:
  $ socat - /tmp/sock1 <<< "show profiling"
  Per-task CPU profiling              : on      # set profiling tasks {on|auto|off}
  Tasks activity:
    function                      calls   cpu_tot   cpu_avg   lat_tot   lat_avg
    ssl_sock_io_cb              3000565   20.96m    419.1us   20.74h    24.89ms
    h1_io_cb                    2019702   9.294s    4.601us   49.22m    1.462ms
    process_stream              2009755   6.570s    3.269us   1.493m    44.57us
    si_cs_io_cb                 1997820   1.566s    783.0ns   2.985m    89.66us
    h1_timeout_task             1009742      -         -      1.647m    97.86us
    accept_queue_process         494509   4.697s    9.498us   1.240m    150.4us
    srv_cleanup_toremove_connections1120   92.32ms   82.43us   463.0ms   413.4us
    srv_cleanup_idle_connections     70   2.703ms   38.61us   204.5us   2.921us
    task_run_applet                  13   1.303ms   100.3us   85.12us   6.548us

  => process_stream() is divided by 100 while ssl_sock_io_cb() is
     multipled by 4

Interestingly, the total HTTPS response time doesn't increase and even very
slightly decreases, with an overall ~1% higher request rate. The net effect
here is a redistribution of the CPU resources between internal tasks, and
in the case of SSL, handshakes wait bit more but everything after completes
faster.

This was made simple enough to be backportable if it helps some users
suffering from high latencies in mixed traffic.
2021-02-26 00:26:03 +01:00
Willy Tarreau
74dea8caea MINOR: task: limit the number of subsequent heavy tasks with flag TASK_HEAVY
While the scheduler is priority-aware and class-aware, and consistently
tries to maintain fairness between all classes, it doesn't make use of a
fine execution budget to compensate for high-latency tasks such as TLS
handshakes. This can result in many subsequent calls adding multiple
milliseconds of latency between the various steps of other tasklets that
don't even depend on this.

An ideal solution would be to add a 4th queue, have all tasks announce
their estimated cost upfront and let the scheduler maintain an auto-
refilling budget to pick from the most suitable queue.

But it turns out that a very simplified version of this already provides
impressive gains with very tiny changes and could easily be backported.
The principle is to reserve a new task flag "TASK_HEAVY" that indicates
that a task is expected to take a lot of time without yielding (e.g. an
SSL handshake typically takes 700 microseconds of crypto computation).
When the scheduler sees this flag when queuing a tasklet, it will place
it into the bulk queue. And during dequeuing, we accept only one of
these in a full round. This means that the first one will be accepted,
will not prevent other lower priority tasks from running, but if a new
one arrives, then the queue stops here and goes back to the polling.
This will allow to collect more important updates for other tasks that
will be batched before the next call of a heavy task.

Preliminary tests consisting in placing this flag on the SSL handshake
tasklet show that response times under SSL stress fell from 14 ms
before the patch to 3.0 ms with the patch, and even 1.8 ms if
tune.sched.low-latency is set to "on".
2021-02-26 00:25:51 +01:00
Amaury Denoyelle
91e55ea3f3 BUG/MINOR: stats: fix compare of no-maint url suffix
Only the first 3 characters are compared for ';no-maint' suffix in
http_handle_stats. Fix it by doing a full match over the entire suffix.

As a side effect, the ';norefresh' suffix matched the inaccurate
comparison, so the maintenance servers were always hidden on the stats
page in this case.

no-maint suffix is present since commit
  3e32036701
  MINOR: stats: also support a "no-maint" show stat modifier

It should be backported up to 2.3.

This fixes github issue #1147.
2021-02-25 14:59:17 +01:00
Christopher Faulet
6c93c4ef08 CLEANUP: muxes: Remove useless if condition in show_fd function
In H1, H2 and FCGI muxes, in the show_fd function, there is duplicated test on
the stream's subs field.

This patch fixes the issue #1142. It may be backported as far as 2.2.
2021-02-25 10:07:24 +01:00
Christopher Faulet
456f45f301 MINOR: server-state: Don't load server-state file for serverless proxies
Just a minor improvement. Proxies with no server are now ignored early. It
may happens for listeners for instance.
2021-02-25 10:02:39 +01:00
Christopher Faulet
3e3d3be708 REORG: server-state: Move functions to deal with server-state in its own file
All functions dealing with the server-state files are moved to
server_state.c.

srv_update_state() function was renammed to srv_state_srv_update().
2021-02-25 10:02:39 +01:00
Christopher Faulet
69beaa91d5 REORG: server: Export and rename some functions updating server info
Some static functions are now exported and renamed to follow the same
pattern of other exported functions. Here is the list :

 * update_server_fqdn: Renamed to srv_update_fqdn and exported
 * update_server_check_addr_port: renamed to srv_update_check_addr_port and exported
 * update_server_agent_addr_port: renamed to srv_update_agent_addr_port and exported
 * update_server_addr: renamed to srv_update_addr
 * update_server_addr_potr: renamed to srv_update_addr_port
 * srv_prepare_for_resolution: exported

This change is mandatory to move all functions dealing with the server-state
files in a separate file.
2021-02-25 10:02:39 +01:00
Christopher Faulet
a67c6bf333 MEDIUM: server: Don't load server-state file if a line is corrupted
This change is not huge but may have a visible impact for users. Now, if a
line of a server-state file is corrupted, the whole file is ignored. A
warning is emitted with the corrupted line number.

In fact, there is no way to recover from a corrupted line. A line is
considered as corrupted if it is too long (truncated line) or if it contains
the wrong number of arguments. In both cases, it means the file was forged
(or at least manually edited). It is safer to ignore it.

Note for now, memory allocation errors are not reported and the
corresponding line is silently ignored.
2021-02-25 10:02:39 +01:00
Christopher Faulet
d0a5e84c8d MINOR: server: Parse and store server-state lines in a dedicated function
Now, srv_state_parse_and_store_line() function is used to parse and store a
line in a tree. It is used for global and local server-state files. This
significatly simplies the apply_server_state() function.
2021-02-25 10:02:39 +01:00
Christopher Faulet
5c37985149 MEDIUM: server: Use a tree to store local server-state lines
Just like for the global server-state file, the line of a local server-state
file are now stored in a tree. This way, the file is fully parsed before
loading the servers state. And with this change, global and local
server-state files are now handled the same way. This will be the
opportunity to factorize the code. It is also a good way to validate the
file before loading any server state.
2021-02-25 10:02:39 +01:00
Christopher Faulet
2c1db104fb MINOR: server: Move loading state of servers in a dedicated function
The loop on the servers of a proxy to load the server states was moved in
the function srv_state_px_update(). This simplify a bit the
apply_server_state() function. It is aslo mandatory to simplify the loading
of local server-state file.
2021-02-25 10:02:39 +01:00
Christopher Faulet
f4d1da90c2 MINOR: server: Remove cached line from global server-state tree when found
When a server for a given backend is found in the tree containing all lines
of the global server-state file, the node is removed from the tree. It is
useless to keep it longer. It is a small improvement, but it may also be
usefull to track the orphan lines (not used for now).
2021-02-25 10:02:39 +01:00
Christopher Faulet
ecfb9b9109 MEDIUM: server: Store parsed params of a server-state line in the tree
Parsed parameters are now stored in the tree of server-state lines. This
way, a line from the global server-state file is only parsed once. Before,
it was parsed a first time to store it in the tree and one more time to load
the server state. To do so, the server-state line object must be allocated
before parsing a line. This means its size must no longer depend on the
length of first parsed parameters (backend and server names). Thus the node
type was changed to use a hashed key instead of a string.
2021-02-25 10:02:39 +01:00
Christopher Faulet
8a14b73ecf MINOR: server: Be more strict when reading the version of a server-state file
Now, we read a full line and expects to found an integer only on it. And if
the line is empty or truncated, an error is returned. If the version is not
valid, an error is also returned. This way, the first line is no longer
partially read.
2021-02-25 10:02:39 +01:00
Christopher Faulet
8b4b6a0d63 CLEANUP: server: Use a local eb-tree to store lines of the global server-state file
There is no reason to use a global variable to store the lines of the global
server-state file. This tree is only used during the file parsing, as a line
cache. Now the eb-tree is declared as a local variable in the
apply_server_state() function.
2021-02-25 10:02:39 +01:00
Christopher Faulet
6d87c58fb4 CLEANUP: server: Rename state_line structure into server_state_line
The structure used to store a server-state line in an eb-tree has a too
generic name. Instead of state_line, the structure is renamed as
server_state_line.
2021-02-25 10:02:39 +01:00
Christopher Faulet
fcb53fbb58 CLEANUP: server: Rename state_line node to node instead of name_name
<state_line.name_name> field is a node in an eb-tree. Thus, instead of
"name_name", we now use "node" to name this field. If is a more explicit
name and not too strange.
2021-02-25 10:02:39 +01:00
Christopher Faulet
131b07be3c MEDIUM: server: Refactor apply_server_state() to make it more readable
The apply_server_state() function is really hard to read. Thus it was
refactored to be more maintainable. First, an helper function is used to get
the server-state file path. Some useless variables were removed and most of
other variables were renamed to be more readable. The error messages are now
prefixed to know the context (global vs per-proxy). Finally, the loop on the
proxies list was simplified.

This patch may seem a bit huge, but the changes are not so important.
2021-02-25 10:02:39 +01:00
Christopher Faulet
2a031ecd96 MINOR: server: Only fill one array when parsing a server-state line
There is no reason to fill two parameter arrays in srv_state_parse_line()
function. Now, only one array is used. The 4th first entries are just
skipped when srv_update_state() is called.
2021-02-25 10:02:39 +01:00
Christopher Faulet
0bf268e184 MINOR: server: Be more strict on the server-state line parsing
The srv_state_parse_line() function was rewritten to be more strict. First
of all, it is possible to make the difference between an ignored line and an
malformed one. Then, only blank characters (spaces and tabs) are now allowed
as field separator. An error is reported for truncated lines or for lines
with an unexpected number of arguments regarding the provided version.
However, for now, errors are ignored by the caller, invalid lines are just
skipped.
2021-02-25 10:02:39 +01:00
Willy Tarreau
2a54ffbf43 MINOR: task: make tasklet wakeup latency measurements more accurate
First, we don't want to measure wakeup times if the call date had not
been set before profiling was enabled at run time. And second, we may
only collect the value before clearing the TASK_IN_LIST bit, otherwise
another wakeup might happen on another thread and replace the call date
we're about to use, hence artificially lower the wakeup times.
2021-02-25 09:44:16 +01:00
Willy Tarreau
b2285de049 MINOR: tasks: also compute the tasklet latency when DEBUG_TASK is set
It is extremely useful to be able to observe the wakeup latency of some
important I/O operations, so let's accept to inflate the tasklet struct
by 8 extra bytes when DEBUG_TASK is set. With just this we have enough
to get live reports like this:

  $ socat - /tmp/sock1 <<< "show profiling"
  Per-task CPU profiling              : on      # set profiling tasks {on|auto|off}
  Tasks activity:
    function                      calls   cpu_tot   cpu_avg   lat_tot   lat_avg
    si_cs_io_cb                 8099492   4.833s    596.0ns   8.974m    66.48us
    h1_io_cb                    7460365   11.55s    1.548us   2.477m    19.92us
    process_stream              7383828   22.79s    3.086us   18.39m    149.5us
    h1_timeout_task                4157      -         -      348.4ms   83.81us
    srv_cleanup_toremove_connections751   39.70ms   52.86us   10.54ms   14.04us
    srv_cleanup_idle_connections     21   1.405ms   66.89us   30.82us   1.467us
    task_run_applet                  16   1.058ms   66.13us   446.2us   27.89us
    accept_queue_process              7   34.53us   4.933us   333.1us   47.58us
2021-02-25 09:44:16 +01:00
Willy Tarreau
45499c56d3 MINOR: task: make grq_total atomic to move it outside of the grq_lock
Instead of decrementing grq_total once per task picked from the global
run queue, let's do it at once after the loop like we do for other
counters. This simplifies the code everywhere. It is not expected to
bring noticeable improvements however, since global tasks tend to be
less common nowadays.
2021-02-25 09:44:16 +01:00
Willy Tarreau
c9afbb10f5 MINOR: task: don't decrement then increment the local run queue
Now we don't need to decrement rq_total when we pick a tack in the tree
to immediately increment it again after installing it into the local
list. Instead, we simply add to the local queue count the number of
globally picked tasks. Avoiding this shows ~0.5% performance gains at
1Mreq/s (2M task switches/s).
2021-02-25 09:44:16 +01:00
Willy Tarreau
2b363ac092 MINOR: task: do not use __task_unlink_rq() from process_runnable_tasks()
As indicated in previous commit, this function tries to guess which tree
the task is in to figure what counters to update, while we already have
that info in the caller. Let's just pick the relevant parts to place them
in the caller.
2021-02-25 09:44:16 +01:00
Willy Tarreau
e7923c1d22 MINOR: task: split the counts of local and global tasks picked
In process_runnable_tasks() we're still calling __task_unlink_rq() to
pick a task, and this function tries to guess where to pick the task
from and which counter to update while the caller's context already
has everything. Worse, the number of local tasks is decremented then
recredited, doubling the operations. In order to avoid this we first
need to keep separate counters for local and global tasks that were
picked. This is what this patch does.
2021-02-25 09:44:16 +01:00
Christopher Faulet
e071f0e6a4 MINOR: htx: Add function to reserve the max possible size for an HTX DATA block
The function htx_reserve_max_data() should be used to get an HTX DATA block
with the max possible size. A current block may be extended or a new one
created, depending on the HTX message state. But the idea is to let the
caller to copy a bunch of data without requesting many new blocks. It is its
responsibility to resize the block at the end, to set the final block size.

This function will be used to parse messages with small chunks. Indeed, we
can have more than 2700 1-byte chunks in a 16Kb of input data. So it is easy
to understand how this function may help to improve the parsing of chunk
messages.
2021-02-24 22:10:01 +01:00
Christopher Faulet
d127ffa9f4 BUG/MEDIUM: resolvers: Reset address for unresolved servers
If the DNS resolution failed for a server, its ip address must be
removed. Otherwise, the server is stopped but keeps its ip. This may be
confusing when the servers state are retrieved on the CLI and it may lead to
undefined behavior if HAproxy is configured to load its servers state from a
file.

This patch should be backported as far as 2.0.
2021-02-24 21:58:46 +01:00
Christopher Faulet
52d4d30109 BUG/MEDIUM: resolvers: Reset server address and port for obselete SRV records
When a SRV record expires, the ip/port assigned to the associated server are
now removed. Otherwise, the server is stopped but keeps its ip/port while
the server hostname is removed. It is confusing when the servers state are
retrieve on the CLI and may be a problem if saved in a server-state
file. Because the reload may fail because of this inconsistency.

Here is an example:

 * Declare a server template in a backend, using the resolver <dns>

server-template test 2 _http._tcp.example.com resolvers dns check

 * 2 SRV records are announced with the corresponding additional
   records. Thus, 2 servers are filled. Here is the "show servers state"
   output :

2 frt 1 test1 192.168.1.1 2 64 0 1 2 15 3 4 6 0 0 0 http1.example.com 8001 _http._tcp.example.com 0 0 - - 0
2 frt 2 test2 192.168.1.2 2 64 0 1 1 15 3 4 6 0 0 0 http2.example.com 8002 _http._tcp.example.com 0 0 - - 0

 * Then, one additional record is removed (or a SRV record is removed, the
   result is the same). Here is the new "show servers state" output :

2 frt 1 test1 192.168.1.1 2 64 0 1 38 15 3 4 6 0 0 0 http1.example.com 8001 _http._tcp.example.com 0 0 - - 0
2 frt 2 test2 192.168.1.2 0 96 0 1 19 15 3 0 14 0 0 0 - 8002 _http._tcp.example.com 0 0 - - 0

On reload, if a server-state file is used, this leads to undefined behaviors
depending on the configuration.

This patch should be backported as far as 2.0.
2021-02-24 21:58:45 +01:00
Baptiste Assmann
b4badf720c BUG/MINOR: resolvers: new callback to properly handle SRV record errors
When a SRV record was created, it used to register the regular server name
resolution callbacks. That said, SRV records and regular server name
resolution don't work the same way, furthermore on error management.

This patch introduces a new call back to manage DNS errors related to
the SRV queries.

this fixes github issue #50.

Backport status: 2.3, 2.2, 2.1, 2.0
2021-02-24 21:58:45 +01:00
Christopher Faulet
a331a1e8eb BUG/MINOR: resolvers: Only renew TTL for SRV records with an additional record
If no additional record is associated to a SRV record, its TTL must not be
renewed. Otherwise the entry never expires. Thus once announced a first
time, the entry remains blocked on the same IP/port except if a new announce
replaces the old one.

Now, the TTL is updated if a SRV record is received while a matching
existing one is found with an additional record or when an new additional
record is assigned to an existing SRV record.

This patch should be backported as far as 2.2.
2021-02-24 21:58:45 +01:00
Christopher Faulet
9c246a4b6c BUG/MINOR: resolvers: Fix condition to release received ARs if not assigned
At the end of resolv_validate_dns_response(), if a received additionnal
record is not assigned to an existing server record, it is released. But the
condition to do so is buggy. If "answer_record" (the received AR) is not
assigned, "tmp_record" is not a valid record object. It is just a dummy
record "representing" the head of the record list.

Now, the condition is far cleaner. This patch must be backported as far as
2.2.
2021-02-24 21:58:45 +01:00
Willy Tarreau
9c6dbf0eea CLEANUP: task: split the large tasklet_wakeup_on() function in two
This function has become large with the multi-queue scheduler. We need
to keep the fast path and the debugging parts inlined, but the rest now
moves to task.c just like was done for task_wakeup(). This has reduced
the code size by 6kB due to less inlining of large parts that are always
context-dependent, and as a side effect, has increased the overall
performance by 1%.
2021-02-24 17:55:58 +01:00
Willy Tarreau
955a11ebfa MINOR: task: move the allocated tasks counter to the per-thread struct
The nb_tasks counter was still global and gets incremented and decremented
for each task_new()/task_free(), and was read in process_runnable_tasks().
But it's only used for stats reporting, so doing this this often is
pointless and expensive. Let's move it to the task_per_thread struct and
have the stats sum it when needed.
2021-02-24 17:42:04 +01:00
Willy Tarreau
eeffb3df41 MINOR: task: limit the remote thread wakeup to the global runqueue only
The test in __task_wakeup() to figure if the remote threads are sleeping
doesn't make sense outside of the global runqueue test, since there are
only two possibilities here: local runqueue or global runqueue, hence a
sleeping thread is another one and can only happen when sending to the
global run queue. Let's move the test inside the "if" block.
2021-02-24 17:42:04 +01:00
Willy Tarreau
018564eaa2 CLEANUP: task: move the tree root detection from __task_wakeup() to task_wakeup()
Historically we used to call __task_wakeup() with a known tree root but
this is not the case and the code has remained needlessly complicated
with the root calculation in task_wakeup() passed in argument to
__task_wakeup() which compares it again.

Let's get rid of this and just move the detection code there. This
eliminates some ifdefs and allows to simplify the test conditions quite
a bit.
2021-02-24 17:42:04 +01:00
Willy Tarreau
1f3b1417b8 CLEANUP: tasks: use a less confusing name for task_list_size
This one is systematically misunderstood due to its unclear name. It
is in fact the number of tasks in the local tasklet list. Let's call
it "tasks_in_list" to remove some of the confusion.
2021-02-24 17:42:04 +01:00
Willy Tarreau
2c41d77ebc MINOR: tasks: do not maintain the rqueue_size counter anymore
This one is exclusively used as a boolean nowadays and is non-zero only
when the thread-local run queue is not empty. Better check the root tree's
pointer and avoid updating this counter all the time.
2021-02-24 17:42:04 +01:00
Willy Tarreau
9c7b8085f4 MEDIUM: task: remove the tasks_run_queue counter and have one per thread
This counter is solely used for reporting in the stats and is the hottest
thread contention point to date. Moving it to the scheduler and having a
separate one for the global run queue dramatically improves the performance,
showing a 12% boost on the request rate on 16 threads!

In addition, the thread debugging output which used to rely on rqueue_size
was not totally accurate as it would only report task counts. Now we can
return the exact thread's run queue length.

It is also interesting to note that there are still a few other task/tasklet
counters in the scheduler that are not efficiently updated because some cover
a single area and others cover multiple areas. It looks like having a distinct
counter for each of the following entries would help and would keep the code
a bit cleaner:
  - global run queue (tree)
  - per-thread run queue (tree)
  - per-thread shared tasklets list
  - per-thread local lists

Maybe even splitting the shared tasklets lists between pure tasklets and
tasks instead of having the whole and tasks would simplify the code because
there remain a number of places where several counters have to be updated.
2021-02-24 17:42:04 +01:00
Willy Tarreau
e3e648c92f BUILD: dns: avoid a build warning when threads are disabled (dss unused)
dns_session_release() only uses its struct dns_stream_server to access
the lock, so a warning is emitted when threads are disabled. Let's mark
it __maybe_unused.
2021-02-24 17:42:04 +01:00
Willy Tarreau
49de68520e MEDIUM: streams: do not use the streams lock anymore
The lock was still used exclusively to deal with the concurrency between
the "show sess" release handler and a stream_new() or stream_free() on
another thread. All other accesses made by "show sess" are already done
under thread isolation. The release handler only requires to unlink its
node when stopping in the middle of a dump (error, timeout etc). Let's
just isolate the thread to deal with this case so that it's compatible
with the dump conditions, and remove all remaining locking on the streams.

This effectively kills the streams lock. The measured gain here is around
1.6% with 4 threads (374krps -> 380k).
2021-02-24 13:54:50 +01:00
Willy Tarreau
a698eb6739 MINOR: streams: use one list per stream instead of a global one
The global streams list is exclusively used for "show sess", to look up
a stream to shut down, and for the hard-stop. Having all of them in a
single list is extremely expensive in terms of locking when using threads,
with performance losses as high as 7% having been observed just due to
this.

This patch makes the list per-thread, since there's no need to have a
global one in this situation. All call places just iterate over all
threads. The most "invasive" changes was in "show sess" where the end
of list needs to go back to the beginning of next thread's list until
the last thread is seen. For now the lock was maintained to keep the
code auditable but a next commit should get rid of it.

The observed performance gain here with only 4 threads is already 7%
(350krps -> 374krps).
2021-02-24 13:53:20 +01:00
Willy Tarreau
5d533e2bad MINOR: cli/streams: make "show sess" dump all streams till the new epoch
Instead of placing the current stream at the end of the stream list when
issuing a "show sess" on the CLI as was done in 2.2 with commit c6e7a1b8e
("MINOR: cli: make "show sess" stop at the last known session"), now we
compare the listed stream's epoch with the dumping stream's and stop on
more recent ones.

This way we're certain to always only dump known streams at the moment we
issue the dump command without having to modify the list. In theory we
could miss some streams if more than 2^31 "show sess" requests are issued
while an old stream remains present, but that's 68 years at 1 "show sess"
per second and it's unlikely we'll keep a process, let alone a stream, that
long.

It could be verified that the count of dumped streams still matches the
one before this change.
2021-02-24 12:12:51 +01:00
Willy Tarreau
b981318c11 MINOR: stream: add an "epoch" to figure which streams appeared when
The "show sess" CLI command currently lists all streams and needs to
stop at a given position to avoid dumping forever. Since 2.2 with
commit c6e7a1b8e ("MINOR: cli: make "show sess" stop at the last known
session"), a hack consists in unlinking the stream running the applet
and linking it again at the current end of the list, in order to serve
as a delimiter. But this forces the stream list to be global, which
affects scalability.

This patch introduces an epoch, which is a global 32-bit counter that
is incremented by the "show sess" command, and which is copied by newly
created streams. This way any stream can know whether any other one is
newer or older than itself.

For now it's only stored and not exploited.
2021-02-24 12:12:51 +01:00
Willy Tarreau
0d03825b93 BUG/MINOR: proxy: wake up all threads when sending the hard-stop signal
The hard-stop event didn't wake threads up. In the past it wasn't an issue
as the poll timeout was limited to 1 second, but since commit 4f59d3861
("MINOR: time: increase the minimum wakeup interval to 60s") it has become
a problem because old processes can remain live for up to one minute after
the hard-stop-after delay. Let's just wake them up.

This may be backported to older releases, though before 2.4 the extra
delay was only one second.
2021-02-24 12:12:46 +01:00
Willy Tarreau
3f5dd2945c BUG/MEDIUM: cli/shutdown sessions: make it thread-safe
There's no locking around the lookup of a stream nor its shutdown
when issuing "shutdown sessions" over the CLI so the risk of crashing
the process is particularly high.

Let's use a thread_isolate() there which is suitable for this task, and
there are not that many alternatives.

This must be backported to 1.8.
2021-02-24 11:11:06 +01:00
Willy Tarreau
92b887e20a BUG/MEDIUM: proxy: use thread-safe stream killing on hard-stop
When setting hard-stop-after, hard_stop() is called at the end to kill
last pending streams. Unfortunately there's no locking there while
walking over the streams list nor when shutting them down, so it's
very likely that some old processes have been crashing or gone wild
due to this. Let's use a thread_isolate() call for this as we don't
have much other choice (and it happens once in the process' life,
that's OK).

This must be backported to 1.8.
2021-02-24 11:08:56 +01:00
Dragan Dosen
ec0a604f27 CLEANUP: vars: make smp_fetch_var() to reuse vars_get_by_desc()
They both do the same thing, so let's remove unneeded code duplication.
2021-02-23 17:23:53 +01:00
Dragan Dosen
14518f2305 BUG/MEDIUM: vars: make functions vars_get_by_{name,desc} thread-safe
This patch adds a lock to functions vars_get_by_name() and
vars_get_by_desc() to protect accesses to the list of variables.

After the variable is fetched, a sample data is duplicated by using
smp_dup() because the variable may be modified by another thread.

This should be backported to all versions supporting vars along with
"BUG/MINOR: sample: secure convs that accept base64 string and var name
as args" which this patch depends on.
2021-02-23 17:22:46 +01:00
Dragan Dosen
9e8db138c9 BUG/MINOR: sample: secure convs that accept base64 string and var name as args
This patch adds a few improvements in order to secure the use of
converters that accept base64 string and variable name as arguments.

The first change is within related function sample_conv_var2smp_str()
which now flags the sample as SMP_F_CONST if the argument is of type
ARGT_STR. This makes the sample more safe for later use.

A new function sample_check_arg_base64() is added. It checks an argument
and fills it with a variable type if the argument string contains a
valid variable name. If failed, it tries to perform a base64 decode
operation on a non-empty string, and fills the argument with the decoded
content which can be used later, without any additional base64dec()
function calls during runtime. This means that haproxy configuration
check may fail if variable lookup fails and an invalid base64 encoded
string is specified as an argument for such converters.

Both converters, "aes_gcm_dec" and "hmac", now use alloc_trash_chunk()
in order to allocate additional buffers for various conversions, and
avoid the use of a pre-allocated trash chunks directly (usually returned
by get_trash_chunk()). The function sample_check_arg_base64() is used
for both converters in order to check their arguments specified within
the haproxy configuration.

This patch should be backported as far as 2.0. However, it is important
to keep in mind a few things. The "hmac" converter is only available
starting with 2.2. In versions prior to 2.2, the "aes_gcm_dec" converter
and sample_conv_var2smp_str() are implemented in src/ssl_sock.c. Thus
the patch will have to be adapted on these versions.

Note that this patch is required for a subsequent, more important fix.
2021-02-23 17:21:46 +01:00
William Lallemand
6c0961442c BUG/MINOR: ssl/cli: potential null pointer dereference in "set ssl cert"
A potential null pointer dereference was reported with an old gcc
version (6.5)

    src/ssl_ckch.c: In function 'cli_parse_set_cert':
    src/ssl_ckch.c:838:7: error: potential null pointer dereference [-Werror=null-dereference]
      if (!ssl_sock_copy_cert_key_and_chain(src->ckch, dst->ckch))
           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    src/ssl_ckch.c:838:7: error: potential null pointer dereference [-Werror=null-dereference]
    src/ssl_ckch.c: In function 'ckchs_dup':
    src/ssl_ckch.c:838:7: error: potential null pointer dereference [-Werror=null-dereference]
      if (!ssl_sock_copy_cert_key_and_chain(src->ckch, dst->ckch))
           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    src/ssl_ckch.c:838:7: error: potential null pointer dereference [-Werror=null-dereference]
    cc1: all warnings being treated as errors

This case does not actually happen but it's better to fix the ckch API
with a NULL check.

Could be backported as far as 2.1.
2021-02-23 14:58:21 +01:00
Ilya Shipitsin
98a9e1b873 BUILD: SSL: introduce fine guard for RAND_keep_random_devices_open
RAND_keep_random_devices_open is OpenSSL specific function, not
implemented in LibreSSL and BoringSSL. Let us define guard
HAVE_SSL_RAND_KEEP_RANDOM_DEVICES_OPEN in include/haproxy/openssl-compat.h
That guard does not depend anymore on HA_OPENSSL_VERSION
2021-02-22 10:35:23 +01:00
Willy Tarreau
c6ba9a0b9b MINOR: sched: have one runqueue ticks counter per thread
The runqueue_ticks counts the number of task wakeups and is used to
position new tasks in the run queue, but since we've had per-thread
run queues, the values there are not very relevant anymore and the
nice value doesn't apply well if some threads are more loaded than
others. In addition, letting all threads compete over a shared counter
is not smart as this may cause some excessive contention.

Let's move this index close to the run queues themselves, i.e. one per
thread and a global one. In addition to improving fairness, this has
increased global performance by 2% on 16 threads thanks to the lower
contention on rqueue_ticks.

Fairness issues were not observed, but if any were to be, this patch
could be backported as far as 2.0 to address them.
2021-02-20 13:03:37 +01:00
Willy Tarreau
4d77bbf856 MINOR: dynbuf: pass offer_buffers() the number of buffers instead of a threshold
Historically this function would try to wake the most accurate number of
process_stream() waiters. But since the introduction of filters which could
also require buffers (e.g. for compression), things started not to be as
accurate anymore. Nowadays muxes and transport layers also use buffers, so
the runqueue size has nothing to do anymore with the number of supposed
users to come.

In addition to this, the threshold was compared to the number of free buffer
calculated as allocated minus used, but this didn't work anymore with local
pools since these counts are not updated upon alloc/free!

Let's clean this up and pass the number of released buffers instead, and
consider that each waiter successfully called counts as one buffer. This
is not rocket science and will not suddenly fix everything, but at least
it cannot be as wrong as it is today.

This could have been marked as a bug given that the current situation is
totally broken regarding this, but this probably doesn't completely fix
it, it only goes in a better direction. It is possible however that it
makes sense in the future to backport this as part of a larger series if
the situation significantly improves.
2021-02-20 12:38:18 +01:00
Willy Tarreau
90f366b595 MINOR: dynbuf: use regular lists instead of mt_lists for buffer_wait
There's no point anymore in keeping mt_lists for the buffer_wait and
buffer_wq since it's thread-local now.
2021-02-20 12:38:18 +01:00
Willy Tarreau
e8e5091510 MINOR: dynbuf: make the buffer wait queue per thread
The buffer wait queue used to be global historically but this doest not
make any sense anymore given that the most common use case is to have
thread-local pools. Thus there's no point waking up waiters of other
threads after releasing an entry, as they won't benefit from it.

Let's move the queue head to the thread_info structure and use
ti->buffer_wq from now on.
2021-02-20 12:38:18 +01:00
Christopher Faulet
28d7876a0c BUG/MINOR: server: Fix test on number of fields allowed in a server-state line
When a server-state line is parsed, a test is performed to be sure there is
enough but not too much fields. However the test is buggy. The bug was
introduced in the commit ea2cdf55e ("MEDIUM: server: Don't introduce a new
server-state file version").

No backport needed.
2021-02-20 12:24:12 +01:00
Christopher Faulet
ea2cdf55e3 MEDIUM: server: Don't introduce a new server-state file version
This revert the commit 63e6cba12 ("MEDIUM: server: add server-states version
2"), but keeping all recent features added to the server-sate file. Instead
of adding a 2nd version for the server-state file format to handle the 5 new
fields added during the 2.4 development, these fields are considered as
optionnal during the parsing. So it is possible to load a server-state file
from HAProxy 2.3. However, from 2.4, these new fields are always dumped in
the server-state file. But it should not be a problem to load it on the 2.3.

This patch seems a bit huge but the diff ignoring the space is much smaller.

The version 2 of the server-state file format is reserved for a real
refactoring to address all issues of the current format.
2021-02-19 18:03:59 +01:00
Christopher Faulet
868a5757e5 BUG/MINOR: server: Be sure to cut the last parsed field of a server-state line
If a line of a server-state file has too many fields, the last one is not
cut on the first following space, as all other fileds. It contains all the
end of the line. It is not the expected behavior. So, now, we cut it on the
next following space, if any. The parsing loop was slighly rewritten.

Note that for now there is no error reported if the line is too long.

This patch may be backported at least as far as 2.1. On 2.0 and prior the
code is not the same. The line parsing is inlined in apply_server_state()
function.
2021-02-19 18:03:59 +01:00
Christopher Faulet
06cd256978 BUG/MINOR: server: Init params before parsing a new server-state line
Same static arrays of parameters are used to parse all server-state
lines. Thus it is important to reinit them to be sure to not get params from
the previous line, eventually from the previous loaded file.

This patch should be backported to all stable branches. However, in 2.0 and
prior, the parsing of server-state lines are inlined in apply_server_state()
function. Thus the patch will have to be adapted on these versions.
2021-02-19 18:03:59 +01:00
Christopher Faulet
2d36df275b BUG/MINOR: http-rules: Always replace the response status on a return action
When a HTTP return action is triggered, HAProxy is responsible to return the
response, based on the configured status code. On the request side, there is
no problem because there is no server response to replace. But on the
response side, we must take care to override the server response status
code, if any, to be sure to use the rigth status code to get the http reply
message.

In short, we must always set the configured status code of the HTTP return
action before returning the http reply to be sure to get the right reply,
the one base on the http return action status code and not a reply based on
the server response status code..

This patch should fix the issue #1139. It must be backported as far as 2.2.
2021-02-19 18:03:59 +01:00
Christopher Faulet
1d7d0f86b8 BUG/MEDIUM: spoe: Resolve the sink if a SPOE logs in a ring buffer
If a SPOE filter is configured to send its logs to a ring buffer, the
corresponding sink must be resolved during the configuration post
parsing. Otherwise, the sink is undefined when a log message is emitted,
crashing HAProxy.

This patch must be backported as far as 2.2.
2021-02-19 18:03:59 +01:00
Amaury Denoyelle
8990b010a0 MINOR: connection: allocate dynamically hash node for backend conns
Remove ebmb_node entry from struct connection and create a dedicated
struct conn_hash_node. struct connection contains now only a pointer to
a conn_hash_node, allocated only for connections where target is of type
OBJ_TYPE_SERVER. This will reduce memory footprints for every
connections that does not need http-reuse such as frontend connections.
2021-02-19 16:59:18 +01:00
Amaury Denoyelle
3d752a8f97 MINOR: mux_h2: do not try to remove front conn from idle trees
In h2_process there was two parts where the connection was removed from
the idle trees, without first checking if the connection is a backend
side.

This should not produce a crash as the node is properly zeroed on
conn_init. However, it is better to explicit the test as it is done on
all other places. Besides it will be mandatory if the node part is
dynamically allocated only for backend connections.
2021-02-19 16:35:13 +01:00
Willy Tarreau
66161326fd MINOR: listener: refine the default MAX_ACCEPT from 64 to 4
The maximum number of connections accepted at once by a thread for a single
listener used to default to 64 divided by the number of processes but the
tasklet-based model is much more scalable and benefits from smaller values.
Experimentation has shown that 4 gives the highest accept rate for all
thread values, and that 3 and 5 come very close, as shown below (HTTP/1
connections forwarded per second at multi-accept 4 and 64):

 ac\thr|    1     2    4     8     16
 ------+------------------------------
      4|   80k  106k  168k  270k  336k
     64|   63k   89k  145k  230k  274k

Some tests were also conducted on SSL and absolutely no change was observed.

The value was placed into a define because it used to be spread all over the
code.

It might be useful at some point to backport this to 2.3 and 2.2 to help
those who observed some performance regressions from 1.6.
2021-02-19 16:02:04 +01:00
Ilya Shipitsin
c47d676bd7 BUILD: ssl: introduce fine guard for OpenSSL specific SCTL functions
SCTL (signed certificate timestamp list) specified in RFC6962
was implemented in c74ce24cd22e8c683ba0e5353c0762f8616e597d, let
us introduce macro HAVE_SSL_SCTL for the HAVE_SSL_SCTL sake,
which in turn is based on SN_ct_cert_scts, which comes in the same commit
2021-02-18 15:55:50 +01:00
William Dauchy
3f4ec7d9fb MINOR: cli: add missing agent commands for set server
we previously forgot to add `agent-*` commands.
Take this opportunity to rewrite the help string in a simpler way for
readability (mainly removing simple quotes)

Signed-off-by: William Dauchy <wdauchy@gmail.com>
2021-02-18 14:58:43 +01:00
Willy Tarreau
5064ab6a98 OPTIM: lb-leastconn: do not unlink the server if it did not change
Due to the two-phase server reservation, there are 3 calls to
fwlc_srv_reposition() per request, one during assign_server() to reserve
the slot, one in connect_server() to commit it, and one in process_stream()
to release it. However only one of the first two will change the key, so
it's needlessly costly to take the lock, remove a server and insert it
again at the same place when we can already figure we ought not to even
have taken the lock.

Furthermore, even when the server needs to move, there can be quite some
contention on the lbprm lock forcing the thread to wait. During this time
the served and nbpend server values might have changed, just like the
lb_node.key itself. Thus we measure the values again under the lock
before updating the tree. Measurements have shown that under contention
with 16 servers and 16 threads, 50% of the updates can be avoided there.

This patch makes the function compute the new key and compare it to
the current one before deciding to move the entry (and does it again
under the lock forthe second test).

This removes between 40 and 50% of the tree updates depending on the
thread contention and the number of servers. The performance gain due
to this (on 16 threads) was:

   16 servers:  415 krps -> 440 krps (6%, contention on lbprm)
    4 servers:  554 krps -> 714 krps (+29%, little contention)

One point worth thinking about is that it's not logic to update the
tree 2-3 times per request while it's only read once. half to 2/3 of
these updates are not needed. An experiment consisting in subscribing
the server to a list and letting the readers reinsert them on the fly
showed further degradation instead of an improvement.

A better approach would probably consist in avoinding writes to shared
cache lines by having the leastconn nodes distinct from the servers,
with one node per value, and having them hold an mt-list with all the
servers having that number of connections. The connection count tree
would then be read-mostly instead of facing heavy writes, and most
write operations would be performed on 1-3 list heads which are way
cheaper to migrate than a tree node, and do not require updating the
last two updated neighbors' cache lines.
2021-02-18 10:06:45 +01:00
Willy Tarreau
85b2fb0358 OPTIM: lb-leastconn: do not take the server lock on take_conn/drop_conn
The operations are only an insert and a delete into the LB tree, which
doesn't require the server's lock at all as the lbprm lock is already
held. Let's drop it. Just for the sake of cleanness, given that the
served and nbpend values used to be atomically updated, we'll use an
atomic load to read them.
2021-02-18 10:06:45 +01:00
Willy Tarreau
6b96e0e9d2 OPTIM: lb-first: do not take the server lock on take_conn/drop_conn
The operations are only an insert and a delete into the LB tree, which
doesn't require the server's lock at all as the lbprm lock is already
held. Let's drop it.
2021-02-18 10:06:45 +01:00
Willy Tarreau
59b0fecfd9 MINOR: lb/api: let callers of take_conn/drop_conn tell if they have the lock
The two algos defining these functions (first and leastconn) do not need the
server's lock. However it's already present in pendconn_process_next_strm()
so the API must be updated so that the functions may take it if needed and
that the callers indicate whether they already own it.

As such, the call places (backend.c and stream.c) now do not take it
anymore, queue.c was unchanged since it's already held, and both "first"
and "leastconn" were updated to take it if not already held.

A quick test on the "first" algo showed a jump from 432 to 565k rps by
just dropping the lock in stream.c!
2021-02-18 10:06:45 +01:00
Willy Tarreau
751153e0f1 OPTIM: server: switch the actconn list to an mt-list
The remaining contention on the server lock solely comes from
sess_change_server() which takes the lock to add and remove a
stream from the server's actconn list. This is both expensive
and pointless since we have mt-lists, and this list is only
used by the CLI's "shutdown server sessions" command!

Let's migrate to an mt-list and remove the need for this costly
lock. By doing so, the request rate increased by ~1.8%.
2021-02-18 10:06:45 +01:00
Willy Tarreau
4e9df2737d BUG/MEDIUM: checks: don't needlessly take the server lock in health_adjust()
The server lock was taken preventively for anything in health_adjust(),
including the static config checks needed to detect that the lock was not
needed, while the function is always called on the response path to update
a server's status. This was responsible for huge contention causing a
performance drop of about 17% on 16 threads. Let's move the lock only
where it should be, i.e. inside the function around the critical sections
only. By doing this, a 16-thread process jumped back from 575 to 675 krps.

This should be backported to 2.3 as the situation degraded there, and
maybe later to 2.2.
2021-02-18 10:06:45 +01:00
Willy Tarreau
64ba5ebadc BUG/MINOR: checks: properly handle wrapping time in __health_adjust()
There's an issue when a server state changes, we use an integer comparison
to decide whether or not to reschedule a test instead of using a wrapping
timer comparison. This will cause some health-checks not to be immediately
triggered half of the time, and some unneeded calls to task_queue() to be
performed in other cases.

This bug has always been there as it was introduced with the commit that
added the feature, 97f07b832 ("[MEDIUM] Decrease server health based on
http responses / events, version 3"). This may be backported everywhere.
2021-02-18 10:06:45 +01:00
Amaury Denoyelle
36441f46c4 MINOR: connection: remove pointers for prehash in conn_hash_params
Replace unneeded pointers for sni/proxy prehash by plain data type.
The code is slightly cleaner.
2021-02-17 16:43:07 +01:00
Amaury Denoyelle
4c09800b76 BUG/MINOR: backend: do not call smp_make_safe for sni conn hash
conn_hash_prehash does not need a nul-terminated string, thus it is only
needed to test if the sni sample is not null before using it as
connection hash input.

Moreover, a bug could be introduced between smp_make_safe and
ssl_sock_set_servername call. Indeed, smp_make_safe may call smp_dup
which duplicates the sample in the trash buffer. If another function
manipulates the trash buffer before the call to ssl_sock_set_servername,
the sni sample might be erased. Currently, no function seems to do that
except make_proxy_line in case proxy protocol is used simultaneously
with the sni on the server.

This does not need to be backported.
2021-02-17 16:38:20 +01:00
Willy Tarreau
9805859f24 BUG/MINOR: session: atomically increment the tracked sessions counter
In session_count_new() the tracked counter was still incremented with
a "++" outside of any lock, resulting in occasional slightly off values
such as the following:

    # table: foo, type: string, size:1000, used:1
    0xb2a398: key=127.1.2.3 use=0 exp=86398318 sess_cnt=999959 http_req_cnt=1000004

Now with the correct atomic increment:

    # table: foo, type: string, size:1000, used:1
    0x7f82a4026d38: key=127.1.2.3 use=0 exp=86399294 sess_cnt=1000004 http_req_cnt=1000004

This can be backported to 1.8.
2021-02-16 18:08:12 +01:00
Emeric Brun
267221557f BUG/MEDIUM: dns: fix multiple double close on fd in dns.c
It seems that fd_delete perform the close of the file descriptor
Se we must not close the fd once again after that.

This should fix issues #1128, #1130 and #1131
2021-02-15 15:42:44 +01:00
Emeric Brun
0e40fda16a BUG/MINOR: dns: fix ring attach control on dns_session_new
Ths patch adds a control on ring_attach which can not currently fail
since we are the first to try to attach.

This should fix issue #1126
2021-02-15 15:24:28 +01:00
Emeric Brun
743afeed33 BUG/MINOR: dns: missing test writing in output channel in session handler
This patch fix a case which should never happen writing
in output channel since we check available room before

This patch should fix github issue #1132
2021-02-15 15:13:01 +01:00
Emeric Brun
526b79219e BUG/MINOR: dns: dns_connect_server must return -1 unsupported nameserver's type
This patch fix returns code in case of dns_connect_server is called
on unsupported type (which should not happen). Doing this we have
the warranty that after a return 0 the fd is never -1.

This patch should fix github issues #1127, #1128 and #1130
2021-02-15 15:12:58 +01:00
Emeric Brun
538bb0441c BUG/MINOR: dns: add test on result getting value from buffer into ring.
This patch adds a missing test in dns_session_io_handler, getting
the query id from the buffer of the ring. An error should never
happen since messages are completely added atomically.

This bug should fix github issue #1133
2021-02-15 15:12:55 +01:00
William Dauchy
3679d0c794 MINOR: stats: add helper to get status string
move listen status to a helper, defining both status enum and string
definition.
this will be helpful to be reused in prometheus code. It also removes
this hard-to-read nested ternary.

Signed-off-by: William Dauchy <wdauchy@gmail.com>
2021-02-15 14:13:32 +01:00
William Dauchy
655e14ef17 MEDIUM: stats: allow to select one field in stats_fill_li_stats
prometheus approach requires to output all values for a given metric
name; meaning we iterate through all metrics, and then iterate in the
inner loop on all objects for this metric.
In order to allow more code reuse, adapt the stats API to be able to
select one field or fill them all otherwise.
From this patch it should be possible to add support for listen stats in
prometheus.

Signed-off-by: William Dauchy <wdauchy@gmail.com>
2021-02-15 14:13:32 +01:00
William Dauchy
b26122b032 CLEANUP: check: fix get_check_status_info declaration
we always put a \n between function name and `{`

Signed-off-by: William Dauchy <wdauchy@gmail.com>
2021-02-15 11:56:31 +01:00
Christopher Faulet
eaab7325a7 BUG/MINOR: server: Remove RMAINT from admin state when loading server state
The RMAINT admin state is dynamic and should be remove from the
srv_admin_state parameter when a server state is loaded from a server-state
file. Otherwise an erorr is reported, the server-state line is ignored and
the server state is not updated.

This patch should fix the issue #576. It must be backported as far as 1.8.
2021-02-15 11:56:31 +01:00
Emeric Brun
56fc5d9ebc MEDIUM: resolvers: add supports of TCP nameservers in resolvers.
This patch introduce the new line "server" to set a TCP
nameserver in a "resolvers" section:

server <name> <address> [param*]
  Used to configure a DNS TCP or stream server. This supports for all
  "server" parameters found in 5.2 paragraph. Some of these parameters
  are irrelevant for DNS resolving. Note: currently 4 queries are pipelined
  on the same connections. A batch of idle connections are removed every
  5 seconds. "maxconn" can be configured to limit the amount of those
  concurrent connections and TLS should also usable if the server supports
. The current implementation limits to 4 pipelined

The name of the line in configuration is open to discussion
and could be changed before the next release.
2021-02-13 10:03:46 +01:00
Emeric Brun
fd647d5f5f MEDIUM: dns: adds code to support pipelined DNS requests over TCP.
This patch introduce the "dns_stream_nameserver" to use DNS over
TCP on strict nameservers.  For the upper layer it is analog to
the api used with udp nameservers except that the user que switch
the name server in "stream" mode at the init using "dns_stream_init".

The fallback from UDP to TCP is not handled and this is not the
purpose of this feature. This is done to choose the transport layer
during the initialization.

Currently there is a hardcoded limit of 4 pipelined transactions
per TCP connections. A batch of idle connections is expired every 5s.
This code is designed to support a maximum DNS message size on TCP: 64k.

Note: this code won't perform retry on unanswered queries this
should be handled by the upper layer
2021-02-13 10:03:46 +01:00
Emeric Brun
c943799c86 MEDIUM: resolvers/dns: split dns.c into dns.c and resolvers.c
This patch splits current dns.c into two files:

The first dns.c contains code related to DNS message exchange over UDP
and in future other TCP. We try to remove depencies to resolving
to make it usable by other stuff as DNS load balancing.

The new resolvers.c inherit of the code specific to the actual
resolvers.

Note:
It was really difficult to obtain a clean diff dur to the amount
of moved code.

Note2:
Counters and stuff related to stats is not cleany separated because
currently counters for both layers are merged and hard to separate
for now.
2021-02-13 10:03:46 +01:00
Emeric Brun
d26a6237ad MEDIUM: resolvers: split resolving and dns message exchange layers.
This patch splits recv and send functions in two layers. the
lowest is responsible of DNS message transactions over
the network. Doing this we could use DNS message layer
for something else than resolving. Load balancing for instance.

This patch also re-works the way to init a nameserver and
introduce the new struct dns_dgram_server to prepare the arrival
of dns_stream_server and the support of DNS over TCP.

The way to retry a send failure of a request because of EAGAIN
was re-worked. Previously there was no control and all "pending"
queries were re-played each time it reaches a EAGAIN. This
patch introduce a ring to stack messages in case of sent
failure. This patch is emptied if poller shows that the
socket is ready again to push messages.
2021-02-13 09:51:10 +01:00
Emeric Brun
d3b4495f0d MINOR: resolvers: rework dns stats prototype because specific to resolvers
Counters are currently stored into lowlevel nameservers struct but
most of them are resolving layer data and increased in the upper layer
So this patch renames the prototype used to allocate/dump them with prefix
'resolv' waiting for a clean split.
2021-02-13 09:43:18 +01:00
Emeric Brun
6a2006ae37 MINOR: resolvers: replace nameserver's resolver ref by generic parent pointer
This will allow to use nameservers in something else than a resolver
section (load balancing for instance).
2021-02-13 09:43:18 +01:00
Emeric Brun
8a55193d4e MEDIUM: resolvers: move resolvers section parsing from cfgparse.c to dns.c
The resolver section parsing is moved from cfgparse.c to dns.c
2021-02-13 09:43:18 +01:00
Emeric Brun
d30e9a1709 MINOR: resolvers: rework prototype suffixes to split resolving and dns.
A lot of prototypes in dns.h are specific to resolvers and must
be renamed to split resolving and DNS layers.
2021-02-13 09:43:18 +01:00
Emeric Brun
456de77bdb MINOR: resolvers: renames resolvers DNS_UPD_* returncodes to RSLV_UPD_*
This patch renames some #defines prefixes from DNS to RSLV.
2021-02-13 09:43:18 +01:00
Emeric Brun
30c766ebbc MINOR: resolvers: renames resolvers DNS_RESP_* errcodes RSLV_RESP_*
This patch renames some #defines prefixes from DNS to RSLV.
2021-02-13 09:43:18 +01:00
Emeric Brun
21fbeedf97 MINOR: resolvers: renames some dns prefixed types using resolv prefix.
@@ -119,8 +119,8 @@ struct act_rule {
-               } dns;                         /* dns resolution */
+               } resolv;                      /* resolving */

-struct dns_options {
+struct resolv_options {
2021-02-13 09:43:18 +01:00
Emeric Brun
08622d3c0a MINOR: resolvers: renames some resolvers specific types to not use dns prefix
This patch applies those changes on names:

-struct dns_resolution {
+struct resolv_resolution {

-struct dns_requester {
+struct resolv_requester {

-struct dns_srvrq {
+struct resolv_srvrq {

@@ -185,12 +185,12 @@ struct stream {

        struct {
-               struct dns_requester *dns_requester;
+               struct resolv_requester *requester;
...
-       } dns_ctx;
+       } resolv_ctx;
2021-02-13 09:43:18 +01:00
Emeric Brun
750fe79cd0 MINOR: resolvers: renames type dns_resolvers to resolvers.
It also renames 'dns_resolvers' head list to sec_resolvers
to avoid conflicts with local variables 'resolvers'.
2021-02-13 09:43:17 +01:00
Emeric Brun
85914e9d9b MINOR: resolvers: renames some resolvers internal types and removes dns prefix
Some types are specific to resolver code and a renamed using
the 'resolv' prefix instead 'dns'.

-struct dns_query_item {
+struct resolv_query_item {

-struct dns_answer_item {
+struct resolv_answer_item {

-struct dns_response_packet {
+struct resolv_response {
2021-02-13 09:43:17 +01:00
Emeric Brun
50c870e4de BUG/MINOR: dns: add missing sent counter and parent id to dns counters.
Resolv callbacks are also updated to rely on counters and not on
nameservers.
"show stat domain dns" will now show the parent id (i.e. resolvers
section name).
2021-02-13 09:43:17 +01:00
Emeric Brun
147b3f05b5 CLEANUP: channel: fix comment in ci_putblk.
The comment is outdated and refer to an old code.

Should be backported until branch 1.5
2021-02-13 09:43:17 +01:00
Emeric Brun
e14b98c08e MINOR: ring: adds new ring_init function.
Adds the new ring_init function to initialize
a pre-allocated ring struct using the given
memory area.
2021-02-13 09:43:17 +01:00
David Carlier
1eb595b8b4 MINOR: tcp: add support for defer-accept on FreeBSD.
FreeBSD has a kernel feature (accf) and a sockopt flag similar to the
Linux's TCP_DEFER_ACCEPT to filter incoming data upon ACK. The main
difference is the filter needs to be placed when the socket actually
listens.
2021-02-13 09:05:02 +01:00
Willy Tarreau
4b10302fd8 MINOR: cfgparse: implement a simple if/elif/else/endif macro block handler
Very often, especially since reg-tests, it would be desirable to be able
to conditionally comment out a config block, such as removing an SSL
binding when SSL is disabled, or enabling HTX only for certain versions,
etc.

This patch introduces a very simple nested block management which takes
".if", ".elif", ".else" and ".endif" directives to take or ignore a block.

For now the conditions are limited to empty string or "0" for false versus
a non-nul integer for true, which already suffices to test environment
variables. Still, it needs to be a bit more advanced with defines, versions
etc.

A set of ".notice", ".warning" and ".alert" statements are provided to
emit messages, often in order to provide advice about how to fix certain
conditions.
2021-02-12 18:54:19 +01:00
Willy Tarreau
49962b58d0 MINOR: peers/cli: do not dump the peers dictionaries by default on "show peers"
The "show peers" output has become huge due to the dictionaries making it
less readable. Now this feature has reached a certain level of maturity
which doesn't warrant to dump it all the time, given that it was essentially
needed by developers. Let's make it optional, and disabled by default, only
when "show peers dict" is requested. The default output reminds about the
command. The output has been divided by 5 :

  $ socat - /tmp/sock1  <<< "show peers dict" | wc -l
  125
  $ socat - /tmp/sock1  <<< "show peers" | wc -l
  26

It could be useful to backport this to recent stable versions.
2021-02-12 17:00:52 +01:00
Christopher Faulet
469676423e CLEANUP: server: Remove useless "filepath" variable in apply_server_state()
This variable is now only used to point on the local server-state file. When
the server-state is global, it is unused. So, we now use "localfilepath"
instead. Thus, the "filepath" variable can safely be removed.
2021-02-12 16:42:00 +01:00
Christopher Faulet
8952ea636b BUG/MINOR: server: Don't call fopen() with server-state filepath set to NULL
When a local server-state file is loaded, if its name is too long, the error
is not properly handled, resulting to a call to fopen() with the "filepath"
variable set to NULL. To fix the bug, when this error occurs, we jump to the
next proxy, via a "continue" statement. And we take case to set "filepath"
variable after the error handling to be sure.

This patch should fix the issue #1111. It must be backported as far as 1.6.
2021-02-12 16:42:00 +01:00
Christopher Faulet
b1d19eab1c CLEANUP: tcpcheck: Remove a useless test on port variable
When a connect rule is evaluated a test is performed on the "port" variable
while it is set to 0 just on the line just above. Just remove this useless
test to make ccpcheck happy.

This patch fixes the issue #1113.
2021-02-12 16:42:00 +01:00
Yves Lafon
b4d3708cb7 MINOR: http: add baseq sample fetch
Symetrical to path/pathq, baseq returns the concatenation of
the Host header and the path including the query string.
2021-02-12 16:38:50 +01:00
Willy Tarreau
7c0b4d861e MEDIUM: cfgparse: allow a proxy to designate the defaults section to use
Now it becomes possible to specify "from foo" on a frontend/listen/backend
or even on a "defaults" line, to mention that defaults section "foo" needs
to be used to preset the proxy's settings.

When not set, the last section remains used. In case the designated name
is found at multiple places, it is rejected and an error indicates two
occurrences of the same name. Similarly, if the section name is found,
its name must only use valid characters. This allows multiple named
defaults section to continue to coexist without the risk that they will
cause trouble by accident.

When it comes to "defaults" relying on another defaults, what happens is
just that a new defaults section is created from the designated one. This
will make it possible for example to reuse some settings such as log-format
like below:

    defaults tcp-clear
        log stdout local0 info
        log-format "%ci:%cp/%b/%si:%sp %ST %ts %U/%B %{+Q}r"

    defaults tcp-ssl
        log stdout local0 info
        log-format "%ci:%cp/%b/%si:%sp %ST %ts %U/%B %{+Q}r ssl=%sslv"

    defaults http-clear from tcp-clear
        mode http

    defaults http-ssl from tcp-ssl
        mode http

    frontend fe1 from http-clear
        bind :8001

    frontend fe2 from http-ssl
        bind :8002

A small corner case remains in the error detection, if a second defaults
section appears with the same name after the point where it was used, and
nobody references it, the duplicate will not be detected. This could be
addressed by performing the syntactic checks in check_config_validity(),
and by postponing the freeing of the defaults, after tagging a defaults
section as explicitly looked up by another section. This doesn't seem
that important at the moment though.
2021-02-12 16:23:46 +01:00
Willy Tarreau
e90904d5a9 MEDIUM: proxy: store the default proxies in a tree by name
Now default proxies are stored into a dedicated tree, sorted by name.
Only unnamed entries are not kept upon new section creation. The very
first call to cfg_parse_listen() will automatically allocate a dummy
defaults section which corresponds to the previous static one, since
the code requires to have one at a few places.

The first immediately visible benefit is that it allows to reuse
alloc_new_proxy() to allocate a defaults section instead of doing it by
hand. And the secret goal is to allow to keep multiple named defaults
section in memory to reuse them from various proxies.
2021-02-12 16:23:46 +01:00
Willy Tarreau
0a0f6a7e4f MINOR: proxy: support storing defaults sections into their own tree
Now we'll have a tree of named defaults sections. The regular insertion
and lookup functions take care of the capability in order to select the
appropriate tree. A new function proxy_destroy_defaults() removes a
proxy from this tree and frees it entirely.
2021-02-12 16:23:46 +01:00
Willy Tarreau
c02ab03142 MINOR: proxy: also store the name for a defaults section
There's an optional name, but till now it was not even saved into the
structure, let's keep it.
2021-02-12 16:23:46 +01:00
Willy Tarreau
ab3410c65d MINOR: cfgparse: use a pointer to the current default proxy
In order to make the default proxy configurable, we'll need to have a
pointer to it which might differ from &defproxy. cfg_parse_listen()
now gets curr_defproxy for this.
2021-02-12 16:23:46 +01:00
Willy Tarreau
5d095c2fac MINOR: cfgparse: check PR_CAP_DEF instead of comparing poiner against defproxy
We want to get rid of this defproxy, let's now simply check the proxy's
capabilities instead of comparing its pointer to the known default one.
2021-02-12 16:23:46 +01:00
Willy Tarreau
80dc6fea59 MINOR: proxy: add a new capability PR_CAP_DEF
In order to more easily distinguish a default proxy from a standard one,
let's introduce a new capability PR_CAP_DEF.
2021-02-12 16:23:46 +01:00
Willy Tarreau
7d0c143185 MINOR: cfgparse: move defproxy to cfgparse-listen as a static
We don't want to expose this one anymore as we'll soon keep multiple
default proxies. Let's move it inside the parser which is the only
place which still uses it, and initialize it on the fly once needed
instead of doing it at boot time.
2021-02-12 16:23:46 +01:00
Willy Tarreau
bb8669ae28 BUG/MINOR: server: parse_server() must take a const for the defproxy
The default proxy was passed as a variable, which in addition to being
a PITA to deal with in the config parser, doesn't feel safe to use when
it ought to be const.

This will only affect new code so no backport is needed.
2021-02-12 16:23:46 +01:00
Willy Tarreau
54fa7e332a BUG/MINOR: tcpcheck: proxy_parse_*check*() must take a const for the defproxy
The default proxy was passed as a variable, which in addition to being
a PITA to deal with in the config parser, doesn't feel safe to use when
it ought to be const.

This will only affect new code so no backport is needed.
2021-02-12 16:23:46 +01:00
Willy Tarreau
220fd70694 BUG/MINOR: extcheck: proxy_parse_extcheck() must take a const for the defproxy
The default proxy was passed as a variable, which in addition to being
a PITA to deal with in the config parser, doesn't feel safe to use when
it ought to be const.

This will only affect new code so no backport is needed.
2021-02-12 16:23:46 +01:00
Willy Tarreau
818ec78af8 MINOR: proxy: always properly reset the just freed default instance pointers
In proxy_free_defaults(); none of the free() calls was followed by a
pointer reset. Not only it's hard to figure if one of them is duplicated,
but this code started to call other functions which might or might not
rely on such just freed pointers. Let's reset them as they should be to
make sure there will never be any case of use-after-free. The 3 functions
called there were inspected and are all unaffected by this so this remains
safe to do right now.
2021-02-12 16:23:46 +01:00
Willy Tarreau
a3320a0509 MINOR: proxy: move the defproxy freeing code to proxy.c
This used to be open-coded in cfgparse-listen.c when facing a "defaults"
keyword. Let's move this into proxy_free_defaults(). This code is ugly and
doesn't even reset the just freed pointers. Let's not change this yet.

This code should probably be merged with a generic proxy deinit function
called from deinit(). However there's a catch on uri_auth which cannot be
freed because it might be used by one or several proxies. We definitely
need refcounts there!
2021-02-12 16:23:46 +01:00
Willy Tarreau
3b06eaec86 MEDIUM: proxy: only take defaults when a default proxy is passed.
The proxy initialization code relies on three phases, allocation,
pre-initialization, and assignments from defaults. This last part is
entirely taken from the defaults proxy when arguments are set. This
sensibly complexifies the initialization code as it requires to always
have a default proxy.

This patch instead first applies the original default settings on a
proxy, and then uses those from a default proxy only if one such is
used. This will allow to initialize a proxy out of any default proxy
while still using valid defaults. A careful inspection of the function
showed that only 4 fields used to be set regardless of the default
proxy, and those were moved to init_new_proxy() where they ought to
have been in the first place.
2021-02-12 16:23:46 +01:00
Willy Tarreau
7683893c70 REORG: proxy: centralize the proxy allocation code into alloc_new_proxy()
This new function takes over the old open-coding that used to be done
for too long in cfg_parse_listen() and it now does everything at once
in a proxy-centric function. The function does all the job of allocating
the structure, initializing it, presetting its defaults from the default
proxy and checking for errors. The code was almost unchanged except for
defproxy being passed as a pointer, and the error message being passed
using memprintf().

This change will be needed to ease reuse of multiple default proxies,
or to create dynamic backends in a distant future.
2021-02-12 16:23:46 +01:00
Willy Tarreau
144289b459 REORG: move init_default_instance() to proxy.c and pass it the defproxy pointer
init_default_instance() was still left in cfgparse.c which is not the
best place to pre-initialize a proxy. Let's place it in proxy.c just
after init_new_proxy(), take this opportunity for renaming it to
proxy_preset_defaults() and taking out init_new_proxy() from it, and
let's pass it the pointer to the default proxy to be initialized instead
of implicitly assuming defproxy. We'll soon be able to exploit this.
Only two call places had to be updated.
2021-02-12 16:23:46 +01:00
Willy Tarreau
09f2e77eb1 BUG/MINOR: tcpheck: the source list must be a const in dup_tcpcheck_var()
This is just an API bug but it's annoying when trying to tidy the code.
The source list passed in argument must be a const and not a variable,
as it's typically the list head from a default proxy and must obviously
not be modified by the function. No backport is needed as it only impacts
new code.
2021-02-12 16:23:46 +01:00
Willy Tarreau
016255a483 BUG/MINOR: http-htx: defpx must be a const in proxy_dup_default_conf_errors()
This is just an API bug but it's annoying when trying to tidy the code.
The default proxy passed in argument must be a const and not a variable.
No backport is needed as it only impacts new code.
2021-02-12 16:23:46 +01:00
Willy Tarreau
b2ec994523 BUG/MINOR: cfgparse: do not mention "addr:port" as supported on proxy lines
The very old error message indicating that a proxy name is mandatory
still had a reference to the optional addr:port argument while this one
is explicitly rejected a few lines later since at least 1.9.

This is harmless but confusing. This can be backported to 2.0.
2021-02-12 16:23:45 +01:00
Willy Tarreau
5bbc676608 BUG/MINOR: stats: revert the change on ST_CONVDONE
In 2.1, commit ee4f5f83d ("MINOR: stats: get rid of the ST_CONVDONE flag")
introduced a subtle bug. By testing curproxy against defproxy in
check_config_validity(), it tried to eliminate the need for a flag
to indicate that stats authentication rules were already compiled,
but by doing so it left the issue opened for the case where a new
defaults section appears after the two proxies sharing the first
one:

      defaults
          mode http
          stats auth foo:bar

      listen l1
          bind :8080

      listen l2
          bind :8181

      defaults
          # just to break above

This config results in:
  [ALERT] 042/113725 (3121) : proxy 'f2': stats 'auth'/'realm' and 'http-request' can't be used at the same time.
  [ALERT] 042/113725 (3121) : Fatal errors found in configuration.

Removing the last defaults remains OK. It turns out that the cleanups
that followed that patch render it useless, so the best fix is to revert
the change (with the up-to-date flags instead). The flag was marked as
belonging to the config. It's not exact but it's the closest to the
reality, as it's not there to configure the behavior but ti mention
that the config parser did its job.

This could be backported as far as 2.1, but in practice it looks like
nobody ever hit it.
2021-02-12 16:23:45 +01:00
Willy Tarreau
937c3ead34 BUG/MEDIUM: config: don't pick unset values from last defaults section
Since commit 1.3.14 with commit 1fa3126ec ("[MEDIUM] introduce separation
between contimeout, and tarpit + queue"), check_config_validity() looks
at the last defaults section to update all proxies' queue and tarpit
timeouts if they were not set!

This was apparently an attempt to properly set them on the fallback values,
except that the fallback values were taken from the default proxy before
looking at the current proxy itself. The worst part of it is that it might
have randomly worked by accident for some configurations when there was a
single defaults section, but has certainly caused too short queue
expirations once another defaults section was added later in the file with
these explicitly defined.

Let's remove the defproxy part and keep only the curproxy ones. This could
be backported everywhere, the bug has been there for 13 years.
2021-02-12 16:23:45 +01:00
Christopher Faulet
f5ea269723 CLEANUP: deinit: release global and per-proxy server-state variables on deinit
The global server-state base directory and file name are now released on
deinit, as well as per-proxy server-state file name.
2021-02-12 16:04:52 +01:00
Christopher Faulet
583b6de68a BUG/MINOR: server: Fix server-state-file-name directive
Since the beginning, this directive is documented to accept an optional file
name. But it should also be possible to use it without any argument to use
the backend name as file name. However, when no argument is provided, an
error is reported during the configuration parsing requesting an argument, a
file name or "use-backend-name". And This last special argument is not
documented.

So, to respect the documentation and to avoid configuration breakages, all
modes are now supported. If this directive is called with no argument or
with "use-backend-name", the backend name is use as file name for the
server-state file. Otherwise, the provided string is used.

In addition, we take care to release any previously allocated file name in
case this directive is defines multiple times in the same backend. And an
error is reported if more than one argument are defined. Finally, the
documentation is updated accordingly. Sections supporting this directive are
also mentioned.

This patch should be backported as far as 1.6.
2021-02-12 16:04:52 +01:00
William Dauchy
ddc7ce9645 MINOR: server: enhance error precision when applying server state
server health checks and agent parameters are written the same way as
others to be able to enahcne code reuse: basically we make use of
parsing and assignment at the same place. It makes it difficult for
error handling to know whether srv object was modified partially or not.
The problem was already present with SRV resolution though.

I was a bit puzzled about the approach to take to be honest, and I did
not wanted to go into a full refactor, so I assumed it was ok to simply
notify whether the line was failed or partially applied.

Signed-off-by: William Dauchy <wdauchy@gmail.com>
2021-02-12 16:04:52 +01:00
William Dauchy
d1a7b85a40 MEDIUM: server: support {check,agent}_addr, agent_port in server state
logical followup from cli commands addition, so that the state server
file stays compatible with the changes made at runtime; use previously
added helper to load server attributes.

also alloc a specific chunk to avoid mixing with other called functions
using it

Signed-off-by: William Dauchy <wdauchy@gmail.com>
2021-02-12 16:04:52 +01:00
William Dauchy
63e6cba12a MEDIUM: server: add server-states version 2
Even if it is possibly too much work for the current usage, it makes
sure we don't break states file from v2.3 to v2.4; indeed, since v2.3,
we introduced two new fields, so we put them aside to guarantee we can
easily reload from a version 1.
The diff seems huge but there is no specific change apart from:
- introduce v2 where it is needed (parsing, update)
- move away from switch/case in update to be able to reuse code
- move srv lock to the whole function to make it easier

this patch confirm how painful it is to maintain this functionality.

Signed-off-by: William Dauchy <wdauchy@gmail.com>
2021-02-12 16:04:52 +01:00
William Dauchy
7cabc06da6 MEDIUM: cli: add agent-port command
this patch allows to set agent port at runtime. In order to align with
both `addr` and `check-addr` commands, also add the possibility to
optionnaly set port on `agent-addr` command. This led to a small
refactor in order to use the same function for both `agent-addr` and
`agent-port` commands.

Signed-off-by: William Dauchy <wdauchy@gmail.com>
2021-02-12 16:04:52 +01:00
William Dauchy
b456e1f389 MEDIUM: cli: add check-addr command
this patch allows to set server health check address at runtime. In
order to align with `addr` command, also allow to set port optionnaly.
This led to a small refactor in order to use the same function for both
`check-addr` and `check-port` commands.
for `check-port`, we however don't permit the change anymore if checks
are not enabled on the server.

This command becomes more and more useful for people having a consul
like architecture:
- the backend server is located on a container with its own IP
- the health checks are done the consul instance located on the host
  with the host IP

Signed-off-by: William Dauchy <wdauchy@gmail.com>
2021-02-12 16:04:52 +01:00
Amaury Denoyelle
edadf192fe BUG/MINOR: backend: fix compilation without ssl
sni_smp/sni_hash are reported as unused on compilation without
USE_OPENSL and may cause compilation failure

This does not need to be backported.
2021-02-12 13:49:42 +01:00
Amaury Denoyelle
1921d20fff MINOR: connection: use proxy protocol as parameter for srv conn hash
Use the proxy protocol frame if proxy protocol is activated on the
server line. Do not add anymore these connections in the private list.
If some requests are made with the same proxy fields, they can reuse
the idle connection.

The reg-tests proxy_protocol_send_unique_id must be adapted has it
relied on the side effect behavior that every requests from a same
connection reused a private server connection. Now, a new connection is
created as expected if the proxy protocol fields differ.
2021-02-12 12:54:04 +01:00
Amaury Denoyelle
d10a200f62 MINOR: connection: use src addr as parameter for srv conn hash
The source address is used as an input to the the server connection hash. The
address and port are used as separate hash inputs. Do not add anymore these
connections in the private list.

This parameter is set only if used in the transparent-proxy mode.
2021-02-12 12:54:04 +01:00
Amaury Denoyelle
f7bdf00071 MINOR: backend: rewrite alloc of connection src address
This commit is similar to
"MINOR: backend: rewrite alloc of stream target address" but with source
address.
2021-02-12 12:54:04 +01:00
Amaury Denoyelle
01a287f1e5 MINOR: connection: use dst addr as parameter for srv conn hash
The destination address is used as an input to the server connection hash. The
address and port are used as separated hash inputs. Note that they are not used
when statically specified on the server line. This is only useful for dynamic
destination address.

This is typically used when the server address is dynamically set via the
set-dst action. The address and port are separated hash parameters.

Most notably, it should fixed set-dst use case (cf github issue #947).
2021-02-12 12:53:56 +01:00
Amaury Denoyelle
68cf3959b3 MINOR: backend: rewrite alloc of stream target address
Change the API of the function used to allocate the stream target
address. This is done in order to be able to allocate the destination
address and use it to reuse a connection sharing with the same address.
In particular, the flag stream SF_ADDR_SET is now set outside of the
function.
2021-02-12 12:53:56 +01:00
Amaury Denoyelle
9b626e3c19 MINOR: connection: use sni as parameter for srv conn hash
The sni parameter is an input to the server connection hash. Do not add
anymore connections with dynamic sni in the private list. Thus, it is
now possible to reuse a server connection if they use the same sni.
2021-02-12 12:48:11 +01:00
Amaury Denoyelle
293dcc400e MINOR: backend: compare conn hash for session conn reuse
Compare the connection hash when reusing a connection from the session.
This ensures that a private connection is reused only if it shares the
same set of parameters.
2021-02-12 12:33:05 +01:00
Amaury Denoyelle
1a58aca84e MINOR: connection: use the srv pointer for the srv conn hash
The pointer of the target server is used as a first parameter for the
server connection hash calcul. This prevents the hash to be null when no
specific parameters are present, and can serve as a simple defense
against an attacker trying to reuse a non-conform connection.
2021-02-12 12:33:05 +01:00
Amaury Denoyelle
81c6f76d3e MINOR: connection: prepare hash calcul for server conns
This is a preliminary work for the calcul of the backend connection
hash. A structure conn_hash_params is the input for the operation,
containing the various specific parameters of a connection.

The high bits of the hash will reflect the parameters present as input.
A set of macros is written to manipulate the connection hash and extract
the parameters/payload.
2021-02-12 12:33:05 +01:00
Amaury Denoyelle
aa890aef3d MINOR: backend: search conn in idle tree after safe on always reuse
With http-reuse always, if no matching safe connection is found, check
in idle tree for a matching one. This is needed because now idle
connections can be differentiated from each other.

If only the safe tree was checked because not empty, but did not contain
a matching connection, we could miss matching entry in idle tree.
2021-02-12 12:33:05 +01:00
Amaury Denoyelle
1399d695c0 MINOR: backend: search conn in idle/safe trees after available
If no matching connection is found on available, check on idle/safe
trees for a matching one. This is needed because now idle connections
can be differentiated from each other.

If only the available list was checked because not empty, but did not
contain a matching connection, we could miss matching entries in idle or
safe trees.
2021-02-12 12:33:05 +01:00
Amaury Denoyelle
f232cb3e9b MEDIUM: connection: replace idle conn lists by eb trees
The server idle/safe/available connection lists are replaced with ebmb-
trees. This is used to store backend connections, with the new field
connection hash as the key. The hash is a 8-bytes size field, used to
reflect specific connection parameters.

This is a preliminary work to be able to reuse connection with SNI,
explicit src/dst address or PROXY protocol.
2021-02-12 12:33:05 +01:00
Amaury Denoyelle
5c7086f6b0 MEDIUM: connection: protect idle conn lists with locks
This is a preparation work for connection reuse with sni/proxy
protocol/specific src-dst addresses.

Protect every access to idle conn lists with a lock. This is currently
strictly not needed because the access to the list are made with atomic
operations. However, to be able to reuse connection with specific
parameters, the list storage will be converted to eb-trees. As this
structure does not have atomic operation, it is mandatory to protect it
with a lock.

For this, the takeover lock is reused. Its role was to protect during
connection takeover. As it is now extended to general idle conns usage,
it is renamed to idle_conns_lock. A new lock section is also
instantiated named IDLE_CONNS_LOCK to isolate its impact on performance.
2021-02-12 12:33:04 +01:00
Amaury Denoyelle
a3bf62ec54 BUG/MINOR: backend: hold correctly lock when killing idle conn
The wrong lock seems to be held when trying to remove another thread
connection if max fd limit has been reached (locking the current thread
instead of the target thread lock).

This could be backported up to 2.0.
2021-02-12 12:32:31 +01:00
Christopher Faulet
cd7126b396 CLEANUP: queue: Remove useless tests on p or pp in pendconn_process_next_strm()
This patch removes unecessary tests on p or pp pointers in
pendconn_process_next_strm() function. This should make cppcheck happy and
avoid false report of null pointer dereference.

This patch should fix the issue #1036.
2021-02-11 11:48:36 +01:00
Ilya Shipitsin
a1e0f387c7 CLEANUP: remove unused variable assigned found by Coverity
this is pure cleanup, no need to backport

2116        if ((end - 1) == (payload + strlen(PAYLOAD_PATTERN))) {
2117                /* if the payload pattern is at the end */
2118                s->pcli_flags |= PCLI_F_PAYLOAD;
    CID 1399833 (#1 of 1): Unused value (UNUSED_VALUE)assigned_value: Assigning value from reql to ret here, but that stored value is overwritten before it can be used.
2119                ret = reql;
2120        }

This patch fixes the issue #1048.
2021-02-11 11:48:36 +01:00
Christopher Faulet
4b524124db BUG/MINOR: tools: Fix a memory leak on error path in parse_dotted_uints()
When an invalid character is found during parsing in parse_dotted_uints()
function, the allocated array of uint must be released. This patch fixes a
memory leak on error path during the configuration parsing.

This patch should fix the issue #1106. It should be backported as far as
2.0. Note that, for 2.1 and 2.0, the function is in src/standard.c
2021-02-11 11:48:36 +01:00
Christopher Faulet
0aeaa290da CLEANUP: muxes: Remove useless calls to b_realign_if_empty()
In H1, H2 and FCGI muxes, b_realign_if_empty() is called to reset the head
of an empty buffer before setting it a specific value to permit the
zero-copy. Thus, we can remove call to b_realign_if_empty().
2021-02-11 11:48:36 +01:00
Christopher Faulet
368936703a MINOR: mux-h1: Be sure EOM flag is set when processing end of outgoing message
When a message is sent, an extra check is performed when the parser is
switch to MSG_DONE state to be sure the EOM flag is really set. This flag is
quite new and replaces the EOM block. Thus, this test is a safeguard waiting
for a proper refactoring of the outgoing side.
2021-02-10 16:25:42 +01:00
Christopher Faulet
337243235f BUG/MEDIUM: mux-h2: Add EOT block when EOM flag is set on an empty HTX message
In the H2 mux, when a empty DATA frame is used to finish a message, just to
set the ES flag, we now only set the EOM flag on the HTX message. However,
if the HTX message is empty, this event will not be properly handled on the
other side because there is no effective data to handle. Thus, it is
interpreted as an abort by the H1 mux.

It is in part caused by the current H1 mux design but also because there is
no way to emit empty HTX block (NOOP HTX block) or to wakeup a mux for send
when there is no data to finish some internal processing.

Thus, for now, to work around this limitation, an EOT HTX block is added by
the H2 mux if a EOM flag is added on an empty HTX message. This case is only
possible when an empty DATA frame with the ES flag is received.

This fix is specific for 2.4. No backport needed.
2021-02-10 16:25:42 +01:00
Christopher Faulet
0a916d2aca BUG/MINOR: mux-h1: Don't blindly skip EOT block for non-chunked messages
In HTTP/2, we may have trailers for messages with a Content-length
header. Thus, when the H2 mux receives a HEADERS frame at the end of a
message, it always emits TLR and EOT HTX blocks. On the H1 mux, if this
happens, these blocks are just skipped because we cannot emit trailers for a
non-chunked message. But the EOT HTX block must not be blindly
ignored. Indeed, there is no longer EOM HTX block to mark the end of the
message. Thus the EOT block, when found, is the end of the message. So we
must handle it to swith in MSG_DONE state.

This fix is specific for 2.4. No backport needed.
2021-02-10 16:25:42 +01:00
Christopher Faulet
0d7e634631 BUG/MINOR: mux-h1: Fix data skipping for bodyless responses
When payload is received for a bodyless response, for instance a response to
a HEAD request, it is silently skipped. Unfortunately, when this happens,
the end of the message is not properly handled. The response remains in the
MSG_DATA state (or MSG_TRAILERS if the message is chunked). In addition,
when a zero-copy is possible, the data are not removed from the channel
buffer and the H1 connection is killed because an error is then triggered.

To fix the bug, the zero-copy is disabled for bodyless responses. It is not
a problem because there is no copy at all. And the last block (DATA or EOT)
is now properly handled.

This bug was introduced by the commit e5596bf53 ("MEDIUM: mux-h1: Don't emit
any payload for bodyless responses").

This fix is specific for 2.4. No backport needed.
2021-02-10 16:25:42 +01:00
Christopher Faulet
a22782b597 BUG/MEDIUM: mux-h1: Always set CS_FL_EOI for response in MSG_DONE state
During the message parsing, if in MSG_DONE state, the CS_FL_EOI flag must
always be set on the conn-stream if following conditions are met :

  * It is a response or
  * It is a request but not a protocol upgrade nor a CONNECT.

For now, there is no test on the message type (request or response). Thus
the CS_FL_EOI flag is not set for a response with a "Connection: upgrade"
header but not a 101 response.

This bug was introduced by the commit 3e1748bbf ("BUG/MINOR: mux-h1: Don't
set CS_FL_EOI too early for protocol upgrade requests"). It was backported
as far as 2.0. Thus, this patch must also be backported as far as 2.0.
2021-02-10 16:25:42 +01:00
Christopher Faulet
bf7175f9b6 BUG/MINOR: http-ana: Don't increment HTTP error counter on internal errors
If internal error is reported by the mux during HTTP request parsing, the
HTTP error counter should not be incremented. It should only be incremented
on parsing error to reflect errors caused by clients.

This patch must be backported as far as 2.0. During the backport, the same
must be performed for 408-request-time-out errors.
2021-02-10 16:22:32 +01:00
Christopher Faulet
f4b7074784 BUG/MINOR: mux-h1: Don't increment HTTP error counter for 408/500/501 errors
The HTTP error counter reflects the number of errors caused by
clients. Thus, In the H1 mux, it should only be increment on parsing errors.

This fix is specific for 2.4. No backport needed.
2021-02-10 16:22:32 +01:00
Willy Tarreau
826f3ab5e6 MINOR: stick-tables/counters: add http_fail_cnt and http_fail_rate data types
Historically we've been counting lots of client-triggered events in stick
tables to help detect misbehaving ones, but we've been missing the same on
the server side, and there's been repeated requests for being able to count
the server errors per URL in order to precisely monitor the quality of
service or even to avoid routing requests to certain dead services, which
is also called "circuit breaking" nowadays.

This commit introduces http_fail_cnt and http_fail_rate, which work like
http_err_cnt and http_err_rate in that they respectively count events and
their frequency, but they only consider server-side issues such as network
errors, unparsable and truncated responses, and 5xx status codes other
than 501 and 505 (since these ones are usually triggered by the client).
Note that retryable errors are purposely not accounted for, so that only
what the client really sees is considered.

With this it becomes very simple to put some protective measures in place
to perform a redirect or return an excuse page when the error rate goes
beyond a certain threshold for a given URL, and give more chances to the
server to recover from this condition. Typically it could look like this
to bypass a URL causing more than 10 requests per second:

  stick-table type string len 80 size 4k expire 1m store http_fail_rate(1m)
  http-request track-sc0 base       # track host+path, ignore query string
  http-request return status 503 content-type text/html \
      lf-file excuse.html if { sc0_http_fail_rate gt 10 }

A more advanced mechanism using gpt0 could even implement high/low rates
to disable/enable the service.

Reg-test converteers_ref_cnt_never_dec.vtc was updated to test it.
2021-02-10 12:27:01 +01:00
Willy Tarreau
e4d247e217 BUG/MINOR: freq_ctr: fix a wrong delay calculation in next_event_delay()
The sleep time calculation in next_event_delay() was wrong because it
was dividing 999 by the number of pending events, and was directly
responsible for an observation made a long time ago that listeners
would eat all the CPU when hammered while globally rate-limited,
because the more the queued events, the least it would wait, and would
ignore the configured frequency to compute the delay.

This was addressed in various ways in listeners through the switch to
the FULL state and the wakeup of manage_global_listener_queue() that
avoids this fast loop, but the calculation made there remained wrong
nevertheless. It's even visible with this patch that the accept
frequency is much more accurate at low values now; for example,
configuring a maxconrate of 10 would give between 8.99 and 11.0 cps
before this patch and between 9.99 and 10.0 with it.

Better fix it now in case it's reused anywhere else and causes confusion
again. It maybe be backported but is probably not worth it.
2021-02-09 17:52:50 +01:00
William Lallemand
3ce6eedb37 MEDIUM: ssl: add a rwlock for SSL server session cache
When adding the server side support for certificate update over the CLI
we encountered a design problem with the SSL session cache which was not
locked.

Indeed, once a certificate is updated we need to flush the cache, but we
also need to ensure that the cache is not used during the update.
To prevent the use of the cache during an update, this patch introduce a
rwlock for the SSL server session cache.

In the SSL session part this patch only lock in read, even if it writes.
The reason behind this, is that in the session part, there is one cache
storage per thread so it is not a problem to write in the cache from
several threads. The problem is only when trying to write in the cache
from the CLI (which could be on any thread) when a session is trying to
access the cache. So there is a write lock in the CLI part to prevent
simultaneous access by a session and the CLI.

This patch also remove the thread_isolate attempt which is eating too
much CPU time and was not protecting from the use of a free ptr in the
session.
2021-02-09 09:43:44 +01:00
Ilya Shipitsin
7ff7747a17 BUILD: ssl: guard SSL_CTX_set_msg_callback with SSL_CTRL_SET_MSG_CALLBACK macro
both SSL_CTX_set_msg_callback and SSL_CTRL_SET_MSG_CALLBACK defined since
ea262260469e49149cb10b25a87dfd6ad3fbb4ba, we can safely switch to that guard
instead of OpenSSL version
2021-02-08 13:49:41 +01:00
William Dauchy
060ffc82d6 CLEANUP: tools: typo in strl2irc mention
`str2irc` does not exist

Signed-off-by: William Dauchy <wdauchy@gmail.com>
2021-02-08 10:49:08 +01:00
William Dauchy
f4300902b9 CLEANUP: check: fix some typo in comments
a few obvious english typo in comments, some of which introduced by
myself quite recently

Signed-off-by: William Dauchy <wdauchy@gmail.com>
2021-02-08 10:49:08 +01:00
Ilya Shipitsin
acf84595a7 CLEANUP: assorted typo fixes in the code and comments
This is 17th iteration of typo fixes
2021-02-08 10:49:08 +01:00
Christopher Faulet
3d6e0e3e04 BUG/MINOR: mux-h1: Don't emit extra CRLF for empty chunked messages
Because of a buggy tests when processing the EOH HTX block, an extra CRLF is
added for empty chunked messages. This bug was introduced by the commit
d1ac2b90c ("MAJOR: htx: Remove the EOM block type and use HTX_FL_EOM
instead").

This fix is specific for 2.4. No backport needed.
2021-02-08 09:43:36 +01:00
Ilya Shipitsin
f00cdb1856 BUILD: ssl: guard SSL_CTX_add_server_custom_ext with special macro
special guard macros HAVE_SSL_CTX_ADD_SERVER_CUSTOM_EXT was defined earlier
exactly for guarding SSL_CTX_add_server_custom_ext, let us use it wherever
appropriate
2021-02-08 00:11:43 +01:00
Ilya Shipitsin
7bbf5866e0 BUILD: ssl: fix typo in HAVE_SSL_CTX_ADD_SERVER_CUSTOM_EXT macro
HAVE_SSL_CTX_ADD_SERVER_CUSTOM_EXT was introduced in ec60909871
however it was defined as HAVE_SL_CTX_ADD_SERVER_CUSTOM_EXT (missing "S")
let us fix typo
2021-02-08 00:11:41 +01:00
Willy Tarreau
133aaa9f11 BUG/MEDIUM: mux-h2: do not quit the demux loop before setting END_REACHED
The demux loop could quit on missing data but the H2_CF_END_REACHED flag
would not be set in this case. This fixes a remaining situation where
previous commit f09612289 ("BUG/MEDIUM: mux-h2: handle remaining read0
cases") could not be sufficient and still leave CLOSE_WAIT. It's harder
to reproduce but was still observed in prod.

Now we quit via the end of the loop which already takes care of shutr.

This should be backported along with the patch above as far as 2.0.
2021-02-05 12:22:54 +01:00
Remi Tricot-Le Breton
25dd0ad123 BUG/MINOR: sock: Unclosed fd in case of connection allocation failure
If allocating a connection object failed right after a successful accept
on a listener, the new file descriptor was not properly closed.

This fixes GitHub issue #905.
It can be backported to 2.3.
2021-02-05 12:14:51 +01:00
Christopher Faulet
1cdc028687 CLEANUP: http-htx: Set buffer area to NULL instead of malloc(0)
During error files conversion to HTX message, in http_str_to_htx(), if a
file is empty, the corresponding buffer's area is initialized with a
malloc(0) and its size is set to 0. There is no problem here. The behaviour
is totally defined. But it is not really intuitive. Instead, we can simply
set the area to NULL.

This patch should fix the issue #1022.
2021-02-05 11:51:44 +01:00
Willy Tarreau
f09612289f BUG/MEDIUM: mux-h2: handle remaining read0 cases
Commit 3d4631fec ("BUG/MEDIUM: mux-h2: fix read0 handling on partial
frames") tried to address an issue introduced in commit aade4edc1 where
read0 wasn't properly handled in the middle of a frame. But the fix was
incomplete for two reasons:

  - first, it would set H2_CF_RCVD_SHUT in h2_recv() after detecting
    a read0 but the condition was guarded by h2_recv_allowed() which
    explicitly excludes read0 ;

  - second, h2_process would only call h2_process_demux() when there
    were still data in the buffer, but closing after a short pause to
    leave a buffer empty wouldn't be caught in this case.

This patch fixes this by properly taking care of the received shutdown
and by also waking up h2_process_demux() on an empty buffer if the demux
is not blocked.

Given the patches above were tagged for backporting to 2.0, this one
should be as well.
2021-02-05 11:48:38 +01:00
Willy Tarreau
ed9892018c MINOR: cli/show_fd: report local and report ports when known
FD dumps are not always easy to match against netstat dumps, and often
require an lsof as a third dump. Let's emit the socket family, and the
local and remore ports when the FD is an IPv4/IPv6 socket, this will
significantly ease the matching.
2021-02-05 10:58:03 +01:00
Willy Tarreau
a84986ae4f BUG/MINOR: ssl: do not try to use early data if not configured
The CO_FL_EARLY_SSL_HS flag was inconditionally set on the connection,
resulting in SSL_read_early_data() always being used first in handshake
calculations. While this seems to work well (probably that there are
fallback paths inside openssl), it's particularly confusing and makes
the debugging quite complicated. It possibly is not optimal by the way.

This flag ought to be set only when early_data is configured on the bind
line. Apparently there used to be a good reason for doing it this way in
1.8 times, but it really does not make sense anymore. It may be OK to
backport this to 2.3 if this helps with troubleshooting, but better not
go too far as it's unlikely to fix any real issue while it could introduce
some in old versions.
2021-02-05 08:04:02 +01:00
Christopher Faulet
a8979a9b59 DOC: server: Add missing params in comment of the server state line parsing
srv_use_ssl and srv_check_port parameters were not mentionned in the comment
of the function parsing a server state line.
2021-02-04 14:00:43 +01:00
William Dauchy
4858fb2e18 MEDIUM: check: align agentaddr and agentport behaviour
in the same manner of agentaddr, we now:
- permit to set agentport through `port` keyword, like it is the case
  for agentaddr through `addr`
- set the priority on `agent-port` keyword when used
- add a flag to be able to test when the value is set like for agentaddr

it makes the behaviour between `addr` and `port` more consistent.

Signed-off-by: William Dauchy <wdauchy@gmail.com>
2021-02-04 14:00:38 +01:00
William Dauchy
1c921cd748 BUG/MINOR: check: consitent way to set agentaddr
small consistency problem with `addr` and `agent-addr` options:
for the both options, the last one parsed is always used to set the
agent-check addr.  Thus these two lines don't have the same behavior:

  server ... addr <addr1> agent-addr <addr2>
  server ... agent-addr <addr2> addr <addr1>

After this patch `agent-addr` will always be the priority option over
`addr`. It means we test the flag before setting agentaddr.
We also fix all the places where we did not set the flag to be coherent
everywhere.

I was not really able to determine where this issue is coming from. So
it is probable we may backport it to all stable version where the agent
is supported.

Signed-off-by: William Dauchy <wdauchy@gmail.com>
2021-02-04 13:55:04 +01:00
William Dauchy
fe03e7d045 MEDIUM: server: adding support for check_port in server state
We can currently change the check-port using the cli command `set server
check-port` but there is a consistency issue when using server state.
This patch aims to fix this problem but will be also a good preparation
work to get rid of checkport flag, so we are able to know when checkport
was set by config.

I am fully aware this is not making github #953 moving forward, I
however think this might be acceptable while waiting for a proper
solution and resolve consistency problem faced with port settings.

Signed-off-by: William Dauchy <wdauchy@gmail.com>
2021-02-04 10:46:52 +01:00
William Dauchy
69f118d7b6 MEDIUM: check: remove checkport checkaddr flag
While trying to fix some consistency problem with the config file/cli
(e.g. check-port cli command does not set the flag), we realised
checkport flag was not necessarily needed. Indeed tcpcheck uses service
port as the last choice if check.port is zero. So we can assume if
check.port is zero, it means it was never set by the user, regardless if
it is by the cli or config file.  In the longterm this will avoid to
introduce a new consistency issue if we forget to set the flag.

in the same manner of checkport flag, we don't really need checkaddr
flag. We can assume if checkaddr is not set, it means it was never set
by the user or config.

Signed-off-by: William Dauchy <wdauchy@gmail.com>
2021-02-04 10:43:00 +01:00
Christopher Faulet
21ca3dfc3a MINOR: dns: Don't set the check port during a server dns resolution
When a server dns resolution is performed, there is no reason to set an
unconfigured check port with the server port. Because by default, if the
check port is not set, the server's one is used. Thus we can remove this
useless assignment. It is mandatory for next improvements.
2021-02-04 10:42:52 +01:00
Christopher Faulet
99497d7dba MINOR: server: Don't set the check port during the update from a state file
When the server state is loaded from a server-state file, there is no reason
to set an unconfigured check port with the server port. Because by default,
if the check port is not set, the server's one is used. Thus we can remove
this useless assignment. It is mandatory for next improvements.
2021-02-04 10:42:45 +01:00
William Dauchy
446db718cb BUG/MINOR: cli: fix set server addr/port coherency with health checks
while reading `update_server_addr_port` I found out some things which
can be seen as incoherency. I hope I did not overlooked anything:

- one comment is stating check's address should be updated if it uses
  the server one; however the condition checks if `SRV_F_CHECKADDR` is
  set; this flag is set when a check address is set; result is that we
  override the check address where I was not expecting it. In fact we
  don't need to update anything here as server addr is used when check
  addr is not set.
- same goes for check agent addr
- for port, it is a bit different, we update the check port if it is
  unset. This is harmless because we also use server port if check port
  is unset. However it creates some incoherency before/after using this
  command, as check port should stay unset througout the life of the
  process unless it is is set by `set server check-port` command.

quite hard to locate the origin of this this issue but the function was
introduced in commit d458adcc52 ("MINOR:
new update_server_addr_port() function to change both server's ADDR and
service PORT"). I was however not able to determine whether this is due
to a change of behavior along the years. So this patch can potentially
be backported up to v1.8 but we must be careful while doing so, as the
code has changed a lot. That being said, the bug being not very
impacting I would be fine keeping it for 2.4 only.

Signed-off-by: William Dauchy <wdauchy@gmail.com>
2021-02-04 09:06:04 +01:00
William Lallemand
e0de0a6b32 MINOR: ssl/cli: flush the server session cache upon 'commit ssl cert'
Flush the SSL session cache when updating a certificate which is used on a
server line. This prevent connections to be established with a cached
session which was using the previous SSL_CTX.

This patch also replace the ha_barrier with a thread_isolate() since there
are more operations to do. The reg-test was also updated to remove the
'no-ssl-reuse' keyword which is now uneeded.
2021-02-03 18:51:01 +01:00
Amaury Denoyelle
377d8786a7 BUG/MINOR: mux_h2: fix incorrect stat titles
Duplicate titles for the stats H2_ST_{OPEN,TOTAL}_{CONN,STREAM}. These
entries are used on csv for the heading.

This must be backported up to 2.3.

This fixes the github issue #1102.
2021-02-03 17:50:45 +01:00
Willy Tarreau
0630038e77 BUG/MEDIUM: ssl: check a connection's status before computing a handshake
As spotted in issue #822, we're having a problem with error detection in
the SSL layer. The problem is that on an overwhelmed machine, accepted
connections can start to pile up, each of them requiring a slow handshake,
and during all this time if the client aborts, the handshake will still be
calculated.

The error controls are properly placed, it's just that the SSL layer
reads records exactly of the advertised size, without having the ability
to encounter a pending connection error. As such if injecting many TLS
connections to a listener with a huge backlog, it's fairly possible to
meet this situation:

  12:50:48.236056 accept4(8, {sa_family=AF_INET, sin_port=htons(62794), sin_addr=inet_addr("127.0.0.1")}, [128->16], SOCK_NONBLOCK) = 1109
  12:50:48.236071 setsockopt(1109, SOL_TCP, TCP_NODELAY, [1], 4) = 0
  (process other connections' handshakes)

  12:50:48.257270 getsockopt(1109, SOL_SOCKET, SO_ERROR, [ECONNRESET], [4]) = 0
  (proof that error was detectable there but this code was added for the PoC)

  12:50:48.257297 recvfrom(1109, "\26\3\1\2\0", 5, 0, NULL, NULL) = 5
  12:50:48.257310 recvfrom(1109, "\1\0\1\3"..., 512, 0, NULL, NULL) = 512

  (handshake calculation taking 700us)

  12:50:48.258004 sendto(1109, "\26\3\3\0z"..., 1421, MSG_DONTWAIT|MSG_NOSIGNAL, NULL, 0) = -1 EPIPE (Broken pipe)
  12:50:48.258036 close(1109)             = 0

The situation was amplified by the multi-queue accept code, as it resulted
in many incoming connections to be accepted long before they could be
handled. Prior to this they would have been accepted and the handshake
immediately started, which would have resulted in most of the connections
waiting in the the system's accept queue, and dying there when the client
aborted, thus the error would have been detected before even trying to
pass them to the handshake code.

As a result, with a listener running on a very large backlog, it's possible
to quickly accept tens of thousands of connections and waste time slowly
running their handshakes while they get replaced by other ones.

This patch adds an SO_ERROR check on the connection's FD before starting
the handshake. This is not pretty as it requires to access the FD, but it
does the job.

Some improvements should be made over the long term so that the transport
layers can report extra information with their ->rcv_buf() call, or at the
very least, implement a ->get_conn_status() function to report various
flags such as shutr, shutw, error at various stages, allowing an upper
layer to inquire for the relevance of engaging into a long operation if
it's known the connection is not usable anymore. An even simpler step
could probably consist in implementing this in the control layer.

This patch is simple enough to be backported as far as 2.0.

Many thanks to @ngaugler for his numerous tests with detailed feedback.
2021-02-02 15:55:53 +01:00
William Lallemand
8695ce0bae BUG/MEDIUM: ssl/cli: abort ssl cert is freeing the old store
The "abort ssl cert" command is buggy and removes the current ckch store,
and instances, leading to SNI removal. It must only removes the new one.

This patch also adds a check in set_ssl_cert.vtc and
set_ssl_server_cert.vtc.

Must be backported as far as 2.2.
2021-02-01 17:58:21 +01:00
William Dauchy
19f7cfc8c3 MINOR: stats: improve max stats descriptions
In order to unify prometheus and stats description, we need to remove
some field reference which are specific to stats implementation:
- `scur` in max current sessions (also reword current session)
- `rate` in max sessions
- `req_rate` in max requests
- `conn_rate` in max connections

Signed-off-by: William Dauchy <wdauchy@gmail.com>
2021-02-01 15:16:33 +01:00
William Dauchy
eedb9b13f4 MINOR: stats: improve pending connections description
In order to unify prometheus and stats description, we need to clarify
the description for pending connections.
- remove the BE reference in counters struct, as it is also used in
  servers
- remove reference of `qcur` field in description as it is specific to
  stats implemention
- try to reword cur and max pending connections description

Signed-off-by: William Dauchy <wdauchy@gmail.com>
2021-02-01 15:16:33 +01:00
Christopher Faulet
7aa3271439 MINOR: checks: Add function to get the result code corresponding to a status
The function get_check_status_result() can now be used to get the result
code (CHK_RES_*) corresponding to a check status (HCHK_STATUS_*). It will be
used by the Prometheus exporter when reporting the check status of a server.
2021-02-01 15:16:33 +01:00
Willy Tarreau
75f72338df BUG/MINOR: activity: take care of late wakeups in "show tasks"
During the call to thread_isolate(), some other threads might have
performed some task_wakeup() which will have a call date past the
one we retrieved. It could be avoided by taking the current date
once we're alone but this would significantly affect the latency
measurements by adding the isolation time. Instead we're now only
accounting positive times, so that late wakeups normally appear
with a zero latency.

No backport is needed, this is 2.4.
2021-01-29 15:07:07 +01:00
Willy Tarreau
d597ec2718 MINOR: listener: export manage_global_listener_queue()
This one pops up in tasks lists when running against a saturated
listener.
2021-01-29 14:29:57 +01:00
Christopher Faulet
c29b4bf946 MINOR: mux-h2: Slightly improve request HEADERS frames sending
In h2s_bck_make_req_headers() function, in the loop on the HTX blocks, the
most common blocks, the headers, are now handled in first, before the
start-line. The same change was already performed on the response HEADERS
frames. Thus the code is more consistent now.
2021-01-29 13:28:43 +01:00
Christopher Faulet
564981369b MINOR: mux-h2: Don't tests the start-line when sending HEADERS frame
When a HEADERS frame is sent, it is always when an HTX start-line block is
found. Thus, in h2s_bck_make_req_headers() and h2s_frt_make_resp_headers()
functions, it is useless to tests the start-line. Instead of being too
defensive, we use BUG_ON() now because it must not happen and must be
handled as a bug.

This patch should fix the issue #1086.
2021-01-29 13:27:57 +01:00
Christopher Faulet
3702f78cf9 MINOR: ssl-sample: Don't check if argument list is set in sample fetches
The list is always defined by definition. Thus there is no reason to test
it.
2021-01-29 13:26:24 +01:00
Christopher Faulet
e6e7a585e9 MINOR: sample: Don't check if argument list is set in sample fetches
The list is always defined by definition. Thus there is no reason to test
it.
2021-01-29 13:26:13 +01:00
Christopher Faulet
72dbcfe66d MINOR: http-conv: Don't check if argument list is set in sample converters
The list is always defined by definition. Thus there is no reason to test
it.
2021-01-29 13:26:02 +01:00
Christopher Faulet
623af93722 MINOR: http-fetch: Don't check if argument list is set in sample fetches
The list is always defined by definition. Thus there is no reason to test
it. There is also plenty of checks on arguments types while it is already
validated during the configuration parsing. But one thing at a time.

This patch should fix the issue #1087.
2021-01-29 13:25:34 +01:00
Christopher Faulet
bdbd5db2a5 BUG/MINOR: stick-table: Always call smp_fetch_src() with a valid arg list
The sample fetch functions must always be called with a valid argument
list. When called by hand, if there is no argument to pass, empty_arg_list must
be used.

In the stick-table code, there are some calls to smp_fetch_src() with NULL as
argument list. It is changed to use empty_arg_list instead. It is not really a
bug because smp_fetch_src() does not use the argument list. But it is an API
bug.

This patch may be backported to all stable branches as a cleanup.
2021-01-29 13:24:16 +01:00
Christopher Faulet
1faeb4c710 MINOR: mux-h1: Remove first useless test on count in h1_process_output()
h1_process_output() function is never called with no data to send (count ==
0). Thus, the first test on count, at the beginning of the function is
useless and may be removed. This way, by reading the code, it is obvious the
<chn_htx> variable is always defined.

This patch should fix the issue #1085.
2021-01-29 13:16:32 +01:00
Willy Tarreau
5c25daa170 MINOR: stick-tables: export process_table_expire()
This handler can take quite some time as it deletes a large number of
entries under a lock, let's export it so that it's immediately visible
in "show profiling".
2021-01-29 12:39:32 +01:00
Willy Tarreau
f6c88421b7 MINOR: peers: export process_peer_sync() to improve traces
This one will probably pop up from time to time in "show profiling",
better have it resolve.
2021-01-29 12:38:42 +01:00
Willy Tarreau
025fc71b47 MINOR: checks: export a few functions that appear often in trace dumps
The check I/O handler, process_chk_conn and server_warmup are often
present in complex backtraces as they're impacted by locking or I/O
issues. Let's export them so that they resolve cleanly.
2021-01-29 12:35:24 +01:00
Willy Tarreau
ac6322dd36 MINOR: muxes: export the timeout and shutr task handlers
These ones appear often in "show tasks" so it's handy to make them
resolve.
2021-01-29 12:33:46 +01:00
Willy Tarreau
02922e19ca MINOR: session: export session_expire_embryonic()
This is only to make it resolve nicely in "show tasks".
2021-01-29 12:27:57 +01:00
Willy Tarreau
fb5401f296 MINOR: listener: export accept_queue_process
This is only to make it resolve in "show tasks".
2021-01-29 12:25:23 +01:00
Willy Tarreau
7eff06e162 MINOR: activity: add a new "show tasks" command to list currently active tasks
This finally adds the long-awaited solution to inspect the run queues
and figure what is eating the CPU or causing latencies. We can even see
the experienced latencies when profiling is enabled. Example on a
saturated process:

> show tasks
Running tasks: 14983 (4 threads)
  function                     places     %    lat_tot   lat_avg
  process_stream                 4948   33.0   5.840m    70.82ms
  h1_io_cb                       2535   16.9      -         -
  main+0x9e670                   2508   16.7   2.930m    70.10ms
  ssl_sock_io_cb                 2499   16.6      -         -
  si_cs_io_cb                    2493   16.6      -         -
2021-01-29 12:12:28 +01:00
Willy Tarreau
cfa7101d59 MINOR: activity: flush scheduler stats on "set profiling tasks on"
If a user enables profiling by hand, it makes sense to reset the stats
counters to provide fresh new measurements. Therefore it's worth using
this as the standard method to reset counters.
2021-01-29 12:10:33 +01:00
Willy Tarreau
1bd67e9b03 MINOR: activity: also report collected tasks stats in "show profiling"
"show profiling" will now dump the stats collected by the scheduler if
profiling was previously enabled. This will immediately make it obvious
what functions are responsible for others' high latencies or which ones
are suffering from others, and should help spot issues like undesired
wakeups.

Example:

Per-task CPU profiling              : on      # set profiling tasks {on|auto|off}
Tasks activity:
  function                      calls   cpu_tot   cpu_avg   lat_tot   lat_avg
  si_cs_io_cb                 5569479   23.37s    4.196us      -         -
  h1_io_cb                    5558654   13.60s    2.446us      -         -
  process_stream               250841   1.476s    5.882us   3.499s    13.95us
  main+0x9e670                    198      -         -      5.526ms   27.91us
  task_run_applet                  17   1.509ms   88.77us   205.8us   12.11us
  srv_cleanup_idle_connections     12   44.51us   3.708us   25.71us   2.142us
  main+0x158c80                     9   48.72us   5.413us      -         -
  srv_cleanup_toremove_connections  5   165.1us   33.02us   123.6us   24.72us
2021-01-29 12:10:33 +01:00
Willy Tarreau
4e2282f9bf MEDIUM: tasks/activity: collect per-task statistics when profiling is enabled
Now when the profiling is enabled, the scheduler wlil update per-function
task-level statistics on number of calls, cpu usage and lateny, that could
later be checked using "show profiling". This will immediately make it
obvious what functions are responsible for others' high latencies or which
ones are suffering from others, and should help spot issues like undesired
wakeups. For now the stats are only collected but not reported (though they
are readable from sched_activity[] under gdb).
2021-01-29 12:10:33 +01:00
Willy Tarreau
3fb6a7b46e MINOR: activity: declare a new structure to collect per-function activity
The new sched_activity structure will be used to collect task-level
activity based on the target function. The principle is to declare a
large enough array to make collisions rare (256 entries), and hash
the function pointer using a reduced XXH to decide where to store the
stats. On first computation an entry is definitely assigned to the
array and it's done atomically. A special entry (0) is used to store
collisions ("others"). The goal is to make it easy and inexpensive for
the scheduler code to use these to store #calls, cpu_time and lat_time
for each task.
2021-01-29 12:10:33 +01:00
Willy Tarreau
aa622b822b MINOR: activity: make profiling more manageable
In 2.0, commit d2d3348ac ("MINOR: activity: enable automatic profiling
turn on/off") introduced an automatic mode to enable/disable profiling.
The problem is that the automatic mode automatically changes to on/off,
which implied that the forced on/off modes aren't sticky anymore. It's
annoying when debugging because as soon as the load decreases, profiling
stops.

This makes a small change which ought to have been done first, which
consists in having two states for "auto" (auto-on, auto-off) to
distinguish them from the forced states. Setting to "auto" in the config
defaults to "auto-off" as before, and setting it on the CLI switches to
auto but keeps the current operating state.

This is simple enough to be backported to older releases if needed.
2021-01-29 12:10:33 +01:00
Willy Tarreau
4deeb1055f MINOR: tools: add print_time_short() to print a condensed duration value
When reporting some values in debugging output we often need to have
some condensed, stable-length values. This function prints a duration
from nanosecond to years with at least 4 digits of accuracy using the
most suitable unit, always on 7 chars.
2021-01-29 12:10:33 +01:00
Amaury Denoyelle
a81bb7197e BUG/MINOR: backend: check available list allocation for reuse
Do not consider reuse connection if available list is not allocated for
the target server. This will prevent a crash when using a standalone
server for an external purpose like socket_tcp/socket_ssl on hlua code.
For the idle/safe lists, they are considered allocated if
srv.max_idle_conns is not null.

Note that the hlua code is currently safe thanks to the additional
checks on proxy http mode and stream reuse policy not never. However,
this might not be sufficient for future code.

This patch should be backported in every branches containing the
following patch :
  7f68d815af (2.4 tree)
  REORG: backend: simplify conn_backend_get
2021-01-28 18:12:07 +01:00
Willy Tarreau
02757d02c2 Revert "BUG/MEDIUM: listener: do not accept connections faster than we can process them"
This reverts commit 62e8aaa1bd.

While is works extremely well to address SSL handshake floods, it prevents
establishment of new connections during regular traffic above 50-60 Gbps,
because for an unknown reason the queue seems to have ~1.7 active tasks
per connection all the time, which makes no sense as these ought to be
waiting on subscribed events. It might uncover a deeper issue but at least
for now a different solution is needed. cf issue #822.

The test is trivial to run, just start a config with tune.runqueue-depth 10
and inject on 1GB objects with more than 10 connections. Try to connect to
the stats socket, it only works once, then the listeners are not dequeued.
2021-01-28 18:11:32 +01:00
Willy Tarreau
62e8aaa1bd BUG/MEDIUM: listener: do not accept connections faster than we can process them
In github issue #822, user @ngaugler reported some performance problems when
dealing with many concurrent SSL connections on restarts, after migrating
from 1.6 to 2.2, indicating a long time required to re-establish connections.

The Run_queue metric in the traces showed an abnormally high number of tasks
in the run queue, likely indicating we were accepting faster than we could
process. And this is indeed one of the differences between 1.6 and 2.2, the
accept I/O loop and the TLS handshakes are totally independent, so much that
they can even run on different threads. In 1.6 the SSL handshake was handled
almost immediately after the accept(), so this was limiting the input rate.
With large maxconn values, as long as there are incoming connections, new
I/Os are scheduled and many of them pass before the handshake, being tagged
for low latency processing.

The result is that handshakes get postponed, and are further postponed as
new connections are accepted. When they are finally able to be processed,
some of them fail as the client is gone, and the client had already queued
new ones. This causes an excess number of apparent connections and total
number of handshakes to be processed, just because we were accepting
connections on a temporarily saturated machine.

The solution is to temporarily pause new incoming connections when the
load already indicates that more tasks are already queued than will be
handled in a poll loop. The difficulty with this usually is to be able
to come back to re-enable the operation, but given that the metric is
the run queue, we just have to queue the global_listener_queue task so
that it gets picked by any thread once the run queues get flushed.

Before this patch, injecting with SSL reneg with 10000 concurrent
connections resulted in 350k tasks in the run queue, and a majority of
handshake timeouts noticed by the client. With the patch, the run queue
fluctuates between 1-3x runqueue-depth, the process is constantly busy, the
accept rate is maximized and clients observe no error anymore.

It would be desirable to backport this patch to 2.3 and 2.2 after some more
testing, provided the accept loop there is compatible.
2021-01-28 16:48:01 +01:00
Christopher Faulet
405f054652 MINOR: h1: Raise the chunk size limit up to (2^52 - 1)
The allowed chunk size was historically limited to 2GB to avoid risk of
overflow. This restriction is no longer necessary because the chunk size is
immediately stored into a 64bits integer after the parsing. Thus, it is now
possible to raise this limit. However to never fed possibly bogus values
from languages that use floats for their integers, we don't get more than 13
hexa-digit (2^52 - 1). 4 petabytes is probably enough !

This patch should fix the issue #1065. It may be backported as far as
2.1. For the 2.0, the legacy HTTP part must be reviewed. But there is
honestely no reason to do so.
2021-01-28 16:37:14 +01:00
Christopher Faulet
73518be595 MINOR: mux-fcgi/trace: add traces at level ERROR for all kind of errors
A number of traces could be added or changed to report errors with
TRACE_ERROR. The goal is to be able to enable error tracing only to detect
anomalies.
2021-01-28 16:37:14 +01:00
Christopher Faulet
26a2643466 MINOR: mux-h1/trace: add traces at level ERROR for all kind of errors
A number of traces could be added or changed to report errors with
TRACE_ERROR. The goal is to be able to enable error tracing only to detect
anomalies.
2021-01-28 16:37:14 +01:00
Amaury Denoyelle
f9dcbeeab3 MEDIUM: h2: send connect protocol h2 settings
In order to announce support for the Extended CONNECT h2 method by
haproxy, always send the ENABLE_CONNECT_PROTOCOL h2 settings. This new
setting has been described in the rfc 8441.

After receiving ENABLE_CONNECT_PROTOCOL, the client is free to use the
Extended CONNECT h2 method. This can notably be useful for the support
of websocket handshake on http/2.
2021-01-28 16:37:14 +01:00
Amaury Denoyelle
c9a0afcc32 MEDIUM: h2: parse Extended CONNECT request to htx
Support for the rfc 8441 Bootstraping WebSockets with HTTP/2

Convert an Extended CONNECT HTTP/2 request into a htx representation.
The htx message uses the GET method with an Upgrade header field to be
fully compatible with the equivalent HTTP/1.1 Upgrade mechanism.

The Extended CONNECT is of the following form :

:method = CONNECT
:protocol = websocket
:scheme = https
:path = /chat
:authority = server.example.com

The new pseudo-header :protocol has been defined and is used to identify
an Extended CONNECT method. Contrary to standard CONNECT, Extended
CONNECT must have :scheme, :path and :authority defined.
2021-01-28 16:37:14 +01:00
Amaury Denoyelle
efe2276a9e MEDIUM: mux_h2: generate Extended CONNECT response
Support for the rfc 8441 Bootstraping WebSockets with HTTP/2

Convert a 101 htx response message to a 200 HTTP/2 response.
2021-01-28 16:37:14 +01:00
Amaury Denoyelle
aad333a9fc MEDIUM: h1: add a WebSocket key on handshake if needed
Add the header Sec-Websocket-Key when generating a h1 handshake websocket
without this header. This is the case when doing h2-h1 conversion.

The key is randomly generated and base64 encoded. It is stored on the session
side to be able to verify response key and reject it if not valid.
2021-01-28 16:37:14 +01:00
Amaury Denoyelle
9bf957335e MEDIUM: mux_h2: generate Extended CONNECT from htx upgrade
Support for the rfc 8441 Bootstraping WebSockets with HTTP/2

Generate an HTTP/2 Extended CONNECT request from a htx Upgrade message.
This conversion is done when seeing the header Connection: Upgrade. A
CONNECT request is written with the :protocol pseudo-header set from the
Upgrade htx header value.

The protocol is saved in the h2s structure. This is needed on the
response side because the protocol is not present on HTTP/2 response but
is needed if the client side is using HTTP/1.1 with 101 status code.
2021-01-28 16:37:14 +01:00
Amaury Denoyelle
7416274914 MEDIUM: h2: parse Extended CONNECT reponse to htx
Support for the rfc 8441 Bootstraping WebSockets with HTTP/2

Convert a 200 status reply from an Extended CONNECT request into a htx
representation. The htx message is set to 101 status code to be fully
compatible with the equivalent HTTP/1.1 Upgrade mechanism.

This conversion is only done if the stream flags H2_SF_EXT_CONNECT_SENT
has been set. This is true if an Extended CONNECT request has already
been seen on the stream.

Besides the 101 status, the additional headers Connection/Upgrade are
added to the htx message. The protocol is set from the value stored in
h2s. Typically it will be extracted from the client request. This is
only used if the client is using h1 as only the HTTP/1.1 101 Response
contains the Upgrade header.
2021-01-28 16:37:14 +01:00
Amaury Denoyelle
5fb48ea7a4 MINOR: mux_h2: define H2_SF_EXT_CONNECT_SENT stream flag
This flag is used to signal that an Extended CONNECT has been sent by
the server mux on the current stream.
This will allow to convert the response to a 101 htx status message.
2021-01-28 16:37:14 +01:00
Amaury Denoyelle
c193823343 MEDIUM: h1: generate WebSocket key on response if needed
Add the Sec-Websocket-Accept header on a websocket handshake response.
This header may be missing if a h2 server is used with a h1 client.

The response key is calculated following the rfc6455. For this, the
handshake request key must be stored in the h1 session, as a new field
name ws_key. Note that this is only done if the message has been
prealably identified as a Websocket handshake request.
2021-01-28 16:37:14 +01:00
Amaury Denoyelle
18ee5c3eb0 MINOR: h1: reject websocket handshake if missing key
If a request is identified as a WebSocket handshake, it must contains a
websocket key header or else it can be reject, following the rfc6455.

A new flag H1_MF_UPG_WEBSOCKET is set on such messages.  For the request
te be identified as a WebSocket handshake, it must contains the headers:
  Connection: upgrade
  Upgrade: websocket

This commit is a compagnon of
"MEDIUM: h1: generate WebSocket key on response if needed" and
"MEDIUM: h1: add a WebSocket key on handshake if needed".

Indeed, it ensures that a WebSocket key is added only from a http/2 side
and not for a http/1 bogus peer.
2021-01-28 16:37:14 +01:00
Christopher Faulet
5b82cc5b5c MEDIUM: http-ana: Deal with L7 retries in HTTP analysers
The code dealing with the copy of requests in the L7-buffer and the
retransmits during L7 retries has been moved in the HTTP analysers. The copy
is now performed in the REQ_HTTP_XFER_BODY analyser and the L7 retries is
performed in the RES_WAIT_HTTP analyser. This way, si_cs_recv() and
si_cs_send() don't care of it anymore. It is much more natural to deal with
L7 retry in HTTP analysers.
2021-01-28 16:37:14 +01:00
Christopher Faulet
991febdfe0 MEDIUM: mux-h2: Don't emit DATA frame for bodyless responses
Some responses must not contain data. Reponses to HEAD requests and 204/304
responses. But there is no warranty that this will be really respected by
the senders or even if it is possible. For instance, the method may be
rewritten by an http-request rule (HEAD->GET). Thus, it is not really
possible to always strip these data from the response at the receive
stage. And the response may be emitted by an applet or an internal service
not strictly following the spec. All that to say that we may be prepared to
handle payload for bodyless responses on the sending path.

In addition, unlike the HTTP/1, it is not really clear that the trailers is
part of the payload or not. Thus, some clients may expect to have the
trailers, if any, in the response to a HEAD request. For instance, the GRPC
status is placed in a trailer and clients rely on it. But what happens for
204 responses then.  Read the following thread for details :

  https://lists.w3.org/Archives/Public/ietf-http-wg/2020OctDec/0040.html

So, thanks to previous patches, it is now possible to know on the sending
path if a response must be bodyless or not. So, for such responses, no DATA
frame is emitted, except eventually the last empty one carring the ES
flag. However, the TRAILERS frames are still emitted. The h2s_skip_data()
function is added to take care to remove HTX DATA blocks without emitting
any DATA frame expect the last one, if there is no trailers.
2021-01-28 16:37:14 +01:00
Christopher Faulet
7d247f0771 MINOR: h2/mux-h2: Add flags to notify the response is known to have no body
The H2 message flag H2_MSGF_BODYLESS_RSP is now used during the request or
the response parsing to notify the mux that, considering the parsed message,
the response is known to have no body. This happens during HEAD requests
parsing and during 204/304 responses parsing.

On the H2 multiplexer, the equivalent flag is set on H2 streams. Thus the
H2_SF_BODYLESS_RESP flag is set on a H2 stream if the H2_MSGF_BODYLESS_RSP
is found after a HEADERS frame parsing. Conversely, this flag is also set
when a HEADERS frame is emitted for HEAD requests and for 204/304 responses.

The H2_SF_BODYLESS_RESP flag will be used to ignore data payload from the
response but not the trailers.
2021-01-28 16:37:14 +01:00
Christopher Faulet
f3e7619041 MINOR: mux-h1: Don't add Connection close/keep-alive header for 1xx messages
No connection header must be added by the H1 mux in 1xx messages, including
101. Existing connection headers remains untouched, especially the "Connection:
upgrade" of 101 responses. This patch only avoids to add "Connection: close" or
"Connection: keep-alive" to 1xx responses.
2021-01-28 16:37:14 +01:00
Christopher Faulet
91fcf21e45 MINOR: mux-h1: Don't emit C-L and T-E headers for 204 and 1xx responses
204 and 1xx responses must not have any payload. Now, the H1 mux takes care
of that in last resort. But they also must not have any C-L or T-E
headers. Thus, if found on the sending path, these headers are ignored.
2021-01-28 16:37:14 +01:00
Christopher Faulet
e5596bf53f MEDIUM: mux-h1: Don't emit any payload for bodyless responses
Some responses must not contain data. Reponses to HEAD requests and 204/304
xresponses. But there is no warranty that this will be really respected by
the senders or even if it is possible. For instance, the method may be
rewritten by an http-request rule (HEAD->GET). Thus, it is not really
possible to always strip the payload from the response at the receive
stage. And the response may be emitted by an applet or an internal service
not strictly following the spec. All that to say that we may be prepared to
handle payload for bodyless responses on the sending path.

So, thanks to previous patches, it is now possible to know on the sending
path if a response must be bodyless or not. So, for such responses, no
payload is emitted, all HTX blocks after the EOH are silently removed
(including the trailers).
2021-01-28 16:37:14 +01:00
Christopher Faulet
5696f5450e MINOR: mux-h1: Add a flag on H1 streams with a response known to be bodyless
In HTTP/1, responses to HEAD requests and 204/304 must not have payload. The
H1S_F_BODYLESS_RESP flag is not set on streams that should handle such
responses, on the client side and the server side.

On the client side, this flag is set when a HEAD request is parsed and when
a 204/304 response is emitted. On the server side, this happends when a HEAD
request is emitted or a 204/304 response is parsed.
2021-01-28 16:37:14 +01:00
Christopher Faulet
d1ac2b90cd MAJOR: htx: Remove the EOM block type and use HTX_FL_EOM instead
The EOM block may be removed. The HTX_FL_EOM flags is enough. Most of time,
to know if the end of the message is reached, we just need to have an empty
HTX message with HTX_FL_EOM flag set. It may also be detected when the last
block of a message with HTX_FL_EOM flag is manipulated.

Removing EOM blocks simplifies the HTX message filling. Indeed, there is no
more edge problems when the message ends but there is no more space to write
the EOM block. However, some part are more tricky. Especially the
compression filter or the FCGI mux. The compression filter must finish the
compression on the last DATA block. Before it was performed on the EOM
block, an extra DATA block with the checksum was added. Now, we must detect
the last DATA block to be sure to finish the compression. The FCGI mux on
its part must be sure to reserve the space for the empty STDIN record on the
last DATA block while this record was inserted on the EOM block.

The H2 multiplexer is probably the part that benefits the most from this
change. Indeed, it is now fairly easier to known when to set the ES flag.

The HTX documentaion has been updated accordingly.
2021-01-28 16:37:14 +01:00
Christopher Faulet
42432f347f MINOR: htx: Rename HTX_FL_EOI flag into HTX_FL_EOM
The HTX_FL_EOI flag is not well named. For now, it is not very used. But
that will change. It will replace the EOM block. Thus, it is renamed.
2021-01-28 16:37:14 +01:00
Christopher Faulet
5be651d4d7 BUG/MAJOR: mux-h1/mux-h2/htx: Fix HTTP tunnel management at the mux level
Tunnel management between the H1 and H2 multiplexers is a bit blurred. And
the HTX is not enough well defined on this point to make things clear. In
fact, Establishing a tunnel between an H2 client and an H1 server, or the
opposite is buggy because the both multiplexers don't handle the EOM block
the same way when a tunnel is established. In fact, the H2 multiplexer is
pretty strict and add an END_STREAM flag when an EOM block is found, while
the H1 multiplexer is more flexible.

The purpose of this patch is to make the EOM block usage pretty clear and to
fix the HTTP multiplexers to really handle HTTP tunnels in the right
way. Now, an EOM block is used to mark the end of an HTTP message,
semantically speaking. That means it may be followed by tunneled data. Thus,
CONNECT requests are now finished by an EOM block, just after the EOH block.

On the H1 multiplexer side, a tunnel is now only established on the response
path. So a CONNECT request remains in a DONE state waiting for the 2xx
response. On the H2 multiplexer side, a flag is used to know an HTTP tunnel
is requested, to not immediately add the END_STREAM flag on the EOM block.

All these changes are sensitives and not backportable because of recent
changes. The same problem exists on earlier versions and should be
addressed. But it will only be possible with a specific patchset.

This patch relies on the following ones :

  * MEDIUM: mux-h1: Properly handle tunnel establishments and aborts
  * MEDIUM: mux-h2: Close streams when processing data for an aborted tunnel
  * MEDIUM: mux-h2: Block client data on server side waiting tunnel establishment
  * MINOR: mux-h2: Add 2 flags to help to properly handle tunnel mode
  * MINOR: mux-h1: Split H1C_F_WAIT_OPPOSITE flag to separate input/output sides
  * MINOR: mux-h1/mux-fcgi: Don't set TUNNEL mode if payload length is unknown
2021-01-28 16:37:14 +01:00
Christopher Faulet
dea2474991 MEDIUM: mux-h1: Properly handle tunnel establishments and aborts
In the same way than the H2 mux, we now bloc data sending on the server side
if a tunnel is not fully established. In addition, if some data are still
pending for a aborted tunnel, an error is triggered and the server
connection is closed.

To do so, we rely on the H1C_F_WAIT_INPUT flag to bloc the output
processing. This patch contributes to fix the tunnel mode between the H1 and
the H2 muxes.
2021-01-28 16:37:14 +01:00
Christopher Faulet
91b21dc8d8 MEDIUM: mux-h2: Close streams when processing data for an aborted tunnel
In the previous patch ("MEDIUM: mux-h2: Block client data on server side
waiting tunnel establishment"), we added a way to block client data for not
fully established tunnel on the server side. This one closes the stream with
an ERR_CANCEL erorr if there are some pending tunneled data while the tunnel
was aborted. This may happen on the client side if a non-empty DATA frame or
an empty DATA frame without the ES flag is received. This may also happen on
the server side if there is a DATA htx block. However in this last case, we
first wait the response is fully forwarded.

This patch contributes to fix the tunnel mode between the H1 and the H2
muxes.
2021-01-28 16:37:14 +01:00
Christopher Faulet
f95f87650f MEDIUM: mux-h2: Block client data on server side waiting tunnel establishment
On the server side, when a tunnel is not fully established, we must block
tunneled data, waiting for the server response. It is mandatory because the
server may refuse the tunnel. This happens when a DATA htx block is
processed in tunnel mode (H2_SF_BODY_TUNNEL flag set) but before the
response HEADERS frame is received (H2_SF_HEADERS_RCVD flag no set). In this
case, the H2_SF_BLK_MBUSY flag is set to mark the stream as busy. This flag
is removed when the tunnel is fully established or aborted.

This patch contributes to fix the tunnel mode between the H1 and the H2
muxes.
2021-01-28 16:37:14 +01:00
Christopher Faulet
d0db42326d MINOR: mux-h2: Add 2 flags to help to properly handle tunnel mode
H2_SF_BODY_TUNNEL and H2_SF_TUNNEL_ABRT flags are added to properly handle
the tunnel mode in the H2 mux. The first one is used to detect tunnel
establishment or fully established tunnel. The second one is used to abort a
tunnel attempt. It is the first commit having as a goal to fix tunnel
establishment between H1 and H2 muxes.

There is a subtlety in h2_rcv_buf(). CS_FL_EOS flag is added on the
conn-stream when ES is received on a tunneled stream. It really reflects the
conn-stream state and is mandatory for next commits.
2021-01-28 16:37:14 +01:00
Christopher Faulet
b385b50fbb MINOR: mux-h1: Split H1C_F_WAIT_OPPOSITE flag to separate input/output sides
The H1C_F_WAIT_OPPOSITE flag is now splitted in 2 flags, H1C_F_WAIT_INPUT
and H1C_F_WAIT_OUTPUT, depending on the side is waiting. The change is a
prerequisite to fix the tunnel mode management in HTTP muxes.

H1C_F_WAIT_INPUT must be used to bloc the output side and to wait for an
event from the input side. H1C_F_WAIT_OUTPUT does the opposite. It bloc the
input side and wait for an event from the output side.
2021-01-28 16:37:14 +01:00
Christopher Faulet
1e857785e9 MINOR: mux-h1/mux-fcgi: Don't set TUNNEL mode if payload length is unknown
Responses with no C-L and T-E headers are no longer switched in TUNNEL mode
and remains in DATA mode instead. The H1 and FCGI muxes are updated
accordingly. This change reflects the real message state. It is not a true
tunnel. Data received are still part of the message.

It is not a bug. However, this message may be backported after some
observation period (at least as far as 2.2).
2021-01-28 16:37:14 +01:00
Christopher Faulet
8989942cfc BUG/MINOR: h2/mux-h2: Reject 101 responses with a PROTOCOL_ERROR h2s error
As stated in the RFC7540, section 8.1.1, the HTTP/2 removes support for the
101 informational status code. Thus a PROTOCOL_ERROR is now returned to the
server if a 101-switching-protocols response is received. Thus, the server
connection is aborted.

This patch may be backported as far as 2.0.
2021-01-28 16:36:40 +01:00
Christopher Faulet
6e6c7b1284 MEDIUM: http-ana: Refuse invalid 101-switching-protocols responses
A 101-switching-protocols response must contain a Connection header with the
Upgrade option. And this response must only be received from a server if the
client explicitly requested a protocol upgrade. Thus, the request must also
contain a Connection header with the Upgrade option. If not, a
502-bad-gateway response is returned to the client. This way, a tunnel is
only established if both sides are agree.

It is closer to what the RFC says, but it remains a bit flexible because
there is no check on the Upgrade header itself. However, that's probably
enough to ensure a tunnel is not established when not requested.

This one is not tagged as a bug. But it may be backported, at least to
2.3. It relies on :

  * MINOR: htx/http-ana: Save info about Upgrade option in the Connection header
2021-01-28 16:27:48 +01:00
Christopher Faulet
576c358508 MINOR: htx/http-ana: Save info about Upgrade option in the Connection header
Add an HTX start-line flag and its counterpart into the HTTP message to
track the presence of the Upgrade option into the Connection header. This
way, without parsing the Connection header again, it will be easy to know if
a client asks for a protocol upgrade and if the server agrees to do so. It
will also be easy to perform some conformance checks when a
101-switching-protocols is received.
2021-01-28 16:27:48 +01:00
Christopher Faulet
0f9395d81e BUG/MAJOR: mux-h1: Properly handle TCP to H1 upgrades
It is the second part and the most important of the fix.

Since the mux-h1 refactoring, and more specifically since the commit
c4bfa59f1 ("MAJOR: mux-h1: Create the client stream as later as possible"),
the upgrade from a TCP client connection to H1 is broken. Indeed, now the H1
mux is responsible to create the frontend conn-stream once the request
headers are fully received. But, to properly support TCP to H1 upgrades, we
must inherit from the existing conn-stream. To do so, if the conn-stream
already exists when the client H1 connection is created, we create a H1
stream in ST_ATTACHED state, but not ST_READY, and the conn-stream is
attached to it. Because the ST_READY state is not set, no data are xferred
to the data layer when h1_rcv_buf() is called and shutdowns are inhibited
except on client aborts. This way, the request is parsed the same way than
for a classical H1 connection. Once the request headers are fully received
and parsed, the data stream is upgraded and the ST_READY state is set.

A tricky case appears when an H2 upgrade is performed because the H2 preface
is matched. In this case, the conn-stream must be detached and destroyed
before switching to the H2 mux and releasing the current H1 mux. We must
also take care to detach and destroy the conn-stream when a timeout
occurres.

This patch relies on the following series of patches :

* BUG/MEDIUM: stream: Don't immediatly ack the TCP to H1 upgrades
* MEDIUM: http-ana: Do nothing in wait-for-request analyzer if not htx
* MINOR: stream: Add a function to validate TCP to H1 upgrades
* MEDIUM: mux-h1: Add ST_READY state for the H1 connections
* MINOR: mux-h1: Wake up instead of subscribe for reads after H1C creation
* MINOR: mux-h1: Try to wake up data layer first before calling its wake callback
* MINOR: stream-int: Take care of EOS in the SI wake callback function
* BUG/MINOR: stream: Don't update counters when TCP to H2 upgrades are performed

This fix is specific for 2.4. No backport needed.
2021-01-28 16:27:48 +01:00
Christopher Faulet
cdd1e2a44b BUG/MEDIUM: stream: Don't immediatly ack the TCP to H1 upgrades
Instead of switching the stream to HTX mode, the request channel is only
reset (the request buffer is xferred to the mux) and the SF_IGNORE flag is
set on the stream. This flag prevent any processing in case of abort. Once
the upgrade confirmed, the flag is removed, in stream_upgrade_from_cs().

It is only the first part of the fix. The next one ("BUG/MAJOR: mux-h1:
Properly handle TCP to H1 upgrades") is also required. Both rely on the
following series of patches :

* MEDIUM: http-ana: Do nothing in wait-for-request analyzer if not htx
* MINOR: stream: Add a function to validate TCP to H1 upgrades
* MEDIUM: mux-h1: Add ST_READY state for the H1 connections
* MINOR: mux-h1: Wake up instead of subscribe for reads after H1C creation
* MINOR: mux-h1: Try to wake up data layer first before calling its wake callback
* MINOR: stream-int: Take care of EOS in the SI wake callback function
* BUG/MINOR: stream: Don't update counters when TCP to H2 upgrades are performed

This fix is specific for 2.4. No backport needed.
2021-01-28 16:27:48 +01:00
Christopher Faulet
da46a0dca7 MEDIUM: http-ana: Do nothing in wait-for-request analyzer if not htx
If http_wait_for_request() analyzer is called with a non-htx stream, nothing
is performed and we return immediatly. For now, it is totally unexpected.
But it will be true during TCP to H1 upgrades, once fixed. Indeed, there
will be a transition period during these upgrades. First the mux will be
upgraded and the not the stream, and finally the stream will be upgraded by
the mux once ready. In the meantime, the stream will still be in raw
mode. Nothing will be performed in wait-for-request analyzer because it will
be the mux responsibility to handle errors.

This patch is required to fix the TCP to H1 upgrades.
2021-01-28 16:27:48 +01:00
Christopher Faulet
4ef84c9c41 MINOR: stream: Add a function to validate TCP to H1 upgrades
TCP to H1 upgrades are buggy for now. When such upgrade is performed, a
crash is experienced. The bug is the result of the recent H1 mux
refactoring, and more specifically because of the commit c4bfa59f1 ("MAJOR:
mux-h1: Create the client stream as later as possible"). Indeed, now the H1
mux is responsible to create the frontend conn-stream once the request
headers are fully received. Thus the TCP to H1 upgrade is a problem because
the frontend conn-stream already exists.

To fix the bug, we must keep this conn-stream and the associate stream and
use it in the H1 mux. To do so, the upgrade will be performed in two
steps. First, the mux is upgraded from mux-pt to mux-h1. Then, the mux-h1
performs the stream upgrade, once the request headers are fully received and
parsed. To do so, stream_upgrade_from_cs() must be used. This function set
the SF_HTX flags to switch the stream to HTX mode, it removes the SF_IGNORE
flags and eventually it fills the request channel with some input data.

This patch is required to fix the TCP to H1 upgrades and is intimately
linked with the next commits.
2021-01-28 16:27:48 +01:00
Christopher Faulet
39c7b6b09d MEDIUM: mux-h1: Add ST_READY state for the H1 connections
An alive H1 connection may be in one of these 3 states :

  * ST_IDLE : not active and is waiting to be reused (no h1s and no cs)
  * ST_EMBRYONIC : active with a h1s but without any cs
  * ST_ATTACHED : active with a h1s and a cs

ST_IDLE and ST_ATTACHED are possible for frontend and backend
connection. ST_EMBRYONIC is only possible on the client side, when we are
waiting for the request headers. The last one is the expected state for an
active connection processing data. These states are mutually exclusives.

Now, there is a new state, ST_READY. It may only be set if ST_ATTACHED is
also set and when the CS is considered as fully active. For now, ST_READY is
set in the same time of ST_ATTACHED. But it will be used to fix TCP to H1
upgrades. Idea is to have an H1 connection in ST_ATTACHED state but not
ST_READY yet and have more or less the same behavior than an H1 connection
in ST_EMBRYONIC state. And when the upgrade is fully achieved, the ST_READY
state may be set and the data layer may be notified accordingly.

So for now, this patch should not change anything. TCP to H1 upgrades are
still buggy. But it is mandatory to make it work properly.
2021-01-28 16:27:48 +01:00
Christopher Faulet
d9ee788b7a MINOR: mux-h1: Wake up H1C after its creation if input buffer is not empty
When a H1 connection is created, we now wakeup the H1C tasklet if there are
some data in the input buffer. If not we only subscribe for reads.

This patch is required to fix the TCP to H1 upgrades.
2021-01-28 16:27:15 +01:00
Christopher Faulet
ad4daf629e MINOR: mux-h1: Try to wake up data layer first before calling its wake callback
Instead of calling the data layer wake callback function, we now first try
to wake it up. If the data layer is subscribed for receives or for sends,
its tasklet is woken up. The wake callback function is only called as the
last chance to notify the data layer.
2021-01-28 16:22:53 +01:00
Christopher Faulet
89e34c261b MEDIUM: stream-int: Take care of EOS if the SI wake callback function
Because si_cs_process() is also the SI wake callback function, it may be
called from the mux layer. Thus, in such cases, it is performed outside any
I/O event and si_cs_recv() is not called. If a read0 is reported by the mux,
via the CS_FL_EOS flag, the event is not handled, because only si_cs_recv()
take care of this flag for now.

It is not a bug, because this does not happens for now. All muxes set this
flag when the data layer retrieve data (via mux->rcv_buf()). But it is safer
to be prepared to handle it from the wake callback. And in fact, it will be
useful to fix the HTTP upgrades of TCP connections (especially TCP>H1>H2
upgrades).

To be sure to not handle the same event twice, it is only handled if the
shutr is not already set on the input channel.
2021-01-28 16:22:04 +01:00
Amaury Denoyelle
08d87b3f49 BUG/MEDIUM: backend: never reuse a connection for tcp mode
The reuse of idle connections should only happen for a proxy with the
http mode. In case of a backend with the tcp mode, the reuse selection
and insertion in session list are skipped.

This behavior is present since commit :
MEDIUM: connection: Add private connections synchronously in session server list
It could also be further exagerated by :
MEDIUM: backend: add reused conn to sess if mux marked as HOL blocking

It can be backported up to 2.3.
2021-01-28 14:18:33 +01:00
William Lallemand
8d67394f69 BUG/MINOR: ssl: init tmp chunk correctly in ssl_sock_load_sctl_from_file()
Use chunk_inistr() for a chunk initialisation in
ssl_sock_load_sctl_from_file() instead of a manual initialisation which
was not initialising head.

Fix issue #1073.

Must be backported as far as 2.2
2021-01-27 14:58:51 +01:00
William Lallemand
b8868498ed CLEANUP: ssl: remove dead code in ckch_inst_new_load_srv_store()
The new ckch_inst_new_load_srv_store() function which mimics the
ckch_inst_new_load_store() function includes some dead code which was
used only in the former function.

Fix issue #1081.
2021-01-27 14:44:59 +01:00
Christopher Faulet
3888b8cd7b BUG/MINOR: stats: Add a break after filling ST_F_MODE field for servers
The previous patch was pushed too quickly (399bf72f6 "BUG/MINOR: stats:
Remove a break preventing ST_F_QCUR to be set for servers"). It was not an
extra break but a misplaced break statement. Thus, now a break statement
must be added after filling the ST_F_MODE field in stats_fill_sv_stats().

No backport needed except if the above commit is backported.
2021-01-27 13:32:26 +01:00
Christopher Faulet
399bf72f66 BUG/MINOR: stats: Remove a break preventing ST_F_QCUR to be set for servers
There is an extra break statement wrongly placed in stats_fill_sv_stats()
function, just before filling the ST_F_QCUR field. It prevents this field to
be set to the right value for servers.

No backport needed except if commit 3a9a4992 ("MEDIUM: stats: allow to
select one field in `stats_fill_sv_stats`") is backported.
2021-01-27 12:48:38 +01:00
William Lallemand
db26e2b00e CLEANUP: ssl: make load_srv_{ckchs,cert} match their bind counterpart
This patch makes things more consistent between the bind_conf functions
and the server ones:

- ssl_sock_load_srv_ckchs() loads the SSL_CTX in the server
  (ssl_sock_load_ckchs() load the SNIs in the bind_conf)

- add the server parameter to ssl_sock_load_srv_ckchs()

- changes made to the ckch_inst are done in
  ckch_inst_new_load_srv_store()
2021-01-26 15:19:36 +01:00
William Lallemand
795bd9ba3a CLEANUP: ssl: remove SSL_CTX function parameter
Since the server SSL_CTX is now stored in the ckch_inst, it is not
needed anymore to pass an SSL_CTX to ckch_inst_new_load_srv_store() and
ssl_sock_load_srv_ckchs().
2021-01-26 15:19:36 +01:00
William Lallemand
1dedb0a82a CLEANUP: ssl/cli: rework free in cli_io_handler_commit_cert()
The new feature allowing the change of server side certificates
introduced duplicated free code. Rework the code in
cli_io_handler_commit_cert() to be more consistent.
2021-01-26 15:19:36 +01:00
Remi Tricot-Le Breton
bb470aa327 MINOR: ssl: Remove client_crt member of the server's ssl context
The client_crt member is not used anymore since the server's ssl context
initialization now behaves the same way as the bind lines one (using
ckch stores and instances).
2021-01-26 15:19:36 +01:00
Remi Tricot-Le Breton
f3eedfe195 MEDIUM: ssl: Enable backend certificate hot update
When trying to update a backend certificate, we should find a
server-side ckch instance thanks to which we can rebuild a new ssl
context and a new ckch instance that replace the previous ones in the
server structure. This way any new ssl session will be built out of the
new ssl context and the newly updated certificate.

This resolves a subpart of GitHub issue #427 (the certificate part)
2021-01-26 15:19:36 +01:00
Remi Tricot-Le Breton
d817dc733e MEDIUM: ssl: Load client certificates in a ckch for backend servers
In order for the backend server's certificate to be hot-updatable, it
needs to fit into the implementation used for the "bind" certificates.
This patch follows the architecture implemented for the frontend
implementation and reuses its structures and general function calls
(adapted for the server side).
The ckch store logic is kept and a dedicated ckch instance is used (one
per server). The whole sni_ctx logic was not kept though because it is
not needed.
All the new functions added in this patch are basically server-side
copies of functions that already exist on the frontend side with all the
sni and bind_cond references removed.
The ckch_inst structure has a new 'is_server_instance' flag which is
used to distinguish regular instances from the server-side ones, and a
new pointer to the server's structure in case of backend instance.
Since the new server ckch instances are linked to a standard ckch_store,
a lookup in the ckch store table will succeed so the cli code used to
update bind certificates needs to be covered to manage those new server
side ckch instances.
2021-01-26 15:19:36 +01:00
Remi Tricot-Le Breton
ec805a32b9 MINOR: ssl: Certificate chain loading refactorization
Move the certificate chain loading code into a dedicated function that
will then be useable elsewhere.
2021-01-26 15:19:36 +01:00
Remi Tricot-Le Breton
442b7f2238 MINOR: ssl: Server ssl context prepare function refactoring
Split the server's ssl context initialization into the general ssl
related initializations and the actual initialization of a single
SSL_CTX structure. This way the context's initialization will be
usable by itself from elsewhere.
2021-01-26 15:19:36 +01:00
Amaury Denoyelle
7f68d815af REORG: backend: simplify conn_backend_get
Reorganize the conditions for the reuse of idle/safe connections :
- reduce code by using variable to store reuse mode and idle/safe conns
  counts
- consider that idle/safe/avail lists are properly allocated if
  max_idle_conns not null. An allocation failure prevents haproxy
  startup.
2021-01-26 14:48:39 +01:00
Amaury Denoyelle
37e25bcd1e CLEANUP: backend: remove an obsolete comment on conn_backend_get
This comment was valid for haproxy 1.8 but now it is obsolete.
2021-01-26 14:48:39 +01:00
Amaury Denoyelle
18c68df558 CLEANUP: srv: fix comment for pool-max-conn
Adjust comment for the unlimited value of pool-max-conn which is -1.
2021-01-26 14:48:39 +01:00
Amaury Denoyelle
69c5c3ab33 BUG/MINOR: config: fix leak on proxy.conn_src.bind_hdr_name
Leak for parsing of option usesrc of the source keyword.

This can be backported to 1.8.
2021-01-26 14:48:39 +01:00
Christopher Faulet
6071c2d12d BUG/MEDIUM: filters/htx: Fix data forwarding when payload length is unknown
It is only a problem on the response path because the request payload length
it always known. But when a filter is registered to analyze the response
payload, the filtering may hang if the server closes just after the headers.

The root cause of the bug comes from an attempt to allow the filters to not
immediately forward the headers if necessary. A filter may choose to hold
the headers by not forwarding any bytes of the payload. For a message with
no payload but a known payload length, there is always a EOM block to
forward. Thus holding the EOM block for bodyless messages is a good way to
also hold the headers. However, messages with an unknown payload length,
there is no EOM block finishing the message, but only a SHUTR flag on the
channel to mark the end of the stream. If there is no payload when it
happens, there is no payload at all to forward. In the filters API, it is
wrongly detected as a condition to not forward the headers.

Because it is not the most used feature and not the obvious one, this patch
introduces another way to hold the message headers at the begining of the
forwarding. A filter flag is added to explicitly says the headers should be
hold. A filter may choose to set the STRM_FLT_FL_HOLD_HTTP_HDRS flag and not
forwad anything to hold the headers. This flag is removed at each call, thus
it must always be explicitly set by filters. This flag is only evaluated if
no byte has ever been forwarded because the headers are forwarded with the
first byte of the payload.

reg-tests/filters/random-forwarding.vtc reg-test is updated to also test
responses with unknown payload length (with and without payload).

This patch must be backported as far as 2.0.
2021-01-26 09:53:52 +01:00
William Dauchy
d3a9a4992b MEDIUM: stats: allow to select one field in stats_fill_sv_stats
prometheus approach requires to output all values for a given metric
name; meaning we iterate through all metrics, and then iterate in the
inner loop on all objects for this metric.
In order to allow more code reuse, adapt the stats API to be able to
select one field or fill them all otherwise.
This patch follows what has already been done on frontend and backend
side.
From this patch it should be possible to remove most of the duplicate
code on prometheuse side for the server.

A few things to note though:
- state require prior calculation, so I moved that to a sort of helper
  `stats_fill_be_stats_computestate`.
- all ST_F*TIME fields requires some minor compute, so I moved it at te
  beginning of the function under a condition.

Signed-off-by: William Dauchy <wdauchy@gmail.com>
2021-01-26 09:24:51 +01:00
William Dauchy
da3b466fc2 MEDIUM: stats: allow to select one field in stats_fill_be_stats
prometheus approach requires to output all values for a given metric
name; meaning we iterate through all metrics, and then iterate in the
inner loop on all objects for this metric.
In order to allow more code reuse, adapt the stats API to be able to
select one field or fill them all otherwise.
This patch follows what has already been done on frontend side.
From this patch it should be possible to remove most of the duplicate
code on prometheuse side for the backend

A few things to note though:
- status and uweight field requires prior compute, so I moved that to a
  sort of helper `stats_fill_be_stats_computesrv`.
- all ST_F*TIME fields requires some minor compute, so I moved it at te
  beginning of the function under a condition.

Signed-off-by: William Dauchy <wdauchy@gmail.com>
2021-01-26 09:24:19 +01:00
Ilya Shipitsin
7704b0e1e1 CLEANUP: assorted typo fixes in the code and comments
This is 16th iteration of typo fixes
2021-01-26 09:16:48 +01:00
William Dauchy
2107a0faf5 CLEANUP: stats: improve field selection for frontend http fields
while working on backend/servers I realised I could have written that in
a better way and avoid one extra break. This is slightly improving
readiness.
also while being here, fix function declaration which was not 100%
accurate.

this patch does not change the behaviour of the code.

Signed-off-by: William Dauchy <wdauchy@gmail.com>
2021-01-25 15:53:28 +01:00
Christopher Faulet
8596bfbafd BUG/MINOR: stats: Init the metric variable when frontend stats are filled
In stats_fill_fe_stats(), some fields are conditionnal (ST_F_HRSP_* for
instance). But unlike unimplemented fields, for those fields, the <metric>
variable is used to fill the <stats> array, but it is not initialized. This
bug as no impact, because these fields are not used. But it is better to fix
it now to avoid future bugs.

To fix it, the metric is now defined and initialized into the for loop.

The bug was introduced by the commit 0ef54397 ("MEDIUM: stats: allow to
select one field in `stats_fill_fe_stats`"). No backport is needed except if
the above commit is backported. It fixes the issue #1063.
2021-01-25 15:53:03 +01:00
Ilya Shipitsin
1fc44d494a BUILD: ssl: guard Client Hello callbacks with HAVE_SSL_CLIENT_HELLO_CB macro instead of openssl version
let us introduce new macro HAVE_SSL_CLIENT_HELLO_CB and guard
callback functions with it
2021-01-22 20:45:24 +01:00
Christopher Faulet
d808f1759d BUG/MINOR: stats: Continue to fill frontend stats on unimplemented metric
A regression was introduced by the commit 0ef54397b ("MEDIUM: stats: allow
to select one field in `stats_fill_fe_stats`"). stats_fill_fe_stats()
function fails on unimplemented metrics for frontends. However, not all
stats metrics are used by frontends. For instance ST_F_QCUR. As a
consequence, the frontends stats are always skipped.

To fix the bug, we just skip unimplemented metric for frontends. An error is
triggered only if a specific field is given and is unimplemented.

No backport is needed except if the above commit is backported.
2021-01-22 17:42:32 +01:00
Bertrand Jacquin
f4c12d4da2 BUILD/MINOR: lua: define _GNU_SOURCE for LLONG_MAX
Lua requires LLONG_MAX defined with __USE_ISOC99 which is set by
_GNU_SOURCE, not necessarely defined by default on old compiler/glibc.

  $ make V=1 TARGET=linux-glibc-legacy USE_THREAD= USE_ACCEPT4= USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1  USE_LUA=1
  ..
  cc -Iinclude  -O2 -g -Wall -Wextra -Wdeclaration-after-statement -fwrapv  -Wno-strict-aliasing -Wno-unused-label -Wno-sign-compare -Wno-unused-parameter  -Wno-missing-field-initializers              -DUSE_EPOLL  -DUSE_NETFILTER -DUSE_PCRE    -DUSE_POLL       -DUSE_TPROXY -DUSE_LINUX_TPROXY -DUSE_LINUX_SPLICE -DUSE_LIBCRYPT -DUSE_CRYPT_H -DUSE_GETADDRINFO -DUSE_OPENSSL -DUSE_LUA -DUSE_FUTEX   -DUSE_ZLIB  -DUSE_CPU_AFFINITY   -DUSE_DL -DUSE_RT      -DUSE_PRCTL -DUSE_THREAD_DUMP     -I/usr/include/openssl101e/  -DUSE_PCRE -I/usr/include  -DCONFIG_HAPROXY_VERSION=\"2.4-dev5-73246d-83\" -DCONFIG_HAPROXY_DATE=\"2021/01/21\" -c -o src/hlua.o src/hlua.c
  In file included from /usr/local/include/lua.h:15,
                   from /usr/local/include/lauxlib.h:15,
                   from src/hlua.c:16:
  /usr/local/include/luaconf.h:581:2: error: #error "Compiler does not support 'long long'. Use option '-DLUA_32BITS'   or '-DLUA_C89_NUMBERS' (see file 'luaconf.h' for details)"
  ..
  cc -Iinclude  -O2 -g -Wall -Wextra -Wdeclaration-after-statement -fwrapv  -Wno-strict-aliasing -Wno-unused-label -Wno-sign-compare -Wno-unused-parameter  -Wno-missing-field-initializers              -DUSE_EPOLL  -DUSE_NETFILTER -DUSE_PCRE    -DUSE_POLL       -DUSE_TPROXY -DUSE_LINUX_TPROXY -DUSE_LINUX_SPLICE -DUSE_LIBCRYPT -DUSE_CRYPT_H -DUSE_GETADDRINFO -DUSE_OPENSSL -DUSE_LUA -DUSE_FUTEX   -DUSE_ZLIB  -DUSE_CPU_AFFINITY   -DUSE_DL -DUSE_RT      -DUSE_PRCTL -DUSE_THREAD_DUMP     -I/usr/include/openssl101e/  -DUSE_PCRE -I/usr/include  -DCONFIG_HAPROXY_VERSION=\"2.4-dev5-73246d-83\" -DCONFIG_HAPROXY_DATE=\"2021/01/21\" -c -o src/hlua_fcn.o src/hlua_fcn.c
  In file included from /usr/local/include/lua.h:15,
                   from /usr/local/include/lauxlib.h:15,
                   from src/hlua_fcn.c:17:
  /usr/local/include/luaconf.h:581:2: error: #error "Compiler does not support 'long long'. Use option '-DLUA_32BITS'   or '-DLUA_C89_NUMBERS' (see file 'luaconf.h' for details)"
  ..

Cc: Thierry Fournier <tfournier@arpalert.org>
2021-01-22 16:17:56 +01:00
Bertrand Jacquin
80839ff8e4 MINOR: lua: remove unused variable
hlua_init() uses 'idx' only in openssl related code, while 'i' is used
in shared code and is safe to be reused. This commit replaces the use of
'idx' with 'i'

  $ make V=1 TARGET=linux-glibc USE_LUA=1 USE_OPENSSL=
  ..
  cc -Iinclude  -O2 -g -Wall -Wextra -Wdeclaration-after-statement -fwrapv -Wno-address-of-packed-member -Wno-unused-label -Wno-sign-compare -Wno-unused-parameter -Wno-clobbered -Wno-missing-field-initializers -Wno-cast-function-type  -Wtype-limits -Wshift-negative-value -Wshift-overflow=2 -Wduplicated-cond -Wnull-dereference   -DUSE_EPOLL  -DUSE_NETFILTER     -DUSE_POLL  -DUSE_THREAD  -DUSE_BACKTRACE   -DUSE_TPROXY -DUSE_LINUX_TPROXY -DUSE_LINUX_SPLICE -DUSE_LIBCRYPT -DUSE_CRYPT_H -DUSE_GETADDRINFO  -DUSE_LUA -DUSE_FUTEX -DUSE_ACCEPT4    -DUSE_CPU_AFFINITY -DUSE_TFO -DUSE_NS -DUSE_DL -DUSE_RT      -DUSE_PRCTL -DUSE_THREAD_DUMP    -I/usr/include/lua5.3 -I/usr/include/lua5.3  -DCONFIG_HAPROXY_VERSION=\"2.4-dev5-37286a-78\" -DCONFIG_HAPROXY_DATE=\"2021/01/21\" -c -o src/hlua.o src/hlua.c
  src/hlua.c: In function 'hlua_init':
  src/hlua.c:9145:6: warning: unused variable 'idx' [-Wunused-variable]
   9145 |  int idx;
        |      ^~~
2021-01-22 16:14:34 +01:00
Willy Tarreau
2cbe2e7f84 BUILD: debug: fix build warning by consuming the write() result
When writing commit a8459b28c ("MINOR: debug: create
ha_backtrace_to_stderr() to dump an instant backtrace") I just forgot
that some distros are a bit extremist about the syscall return values.

  src/debug.c: In function `ha_backtrace_to_stderr':
  src/debug.c:147:3: error: ignoring return value of `write', declared with attribute warn_unused_result [-Werror=unused-result]
     write(2, b.area, b.data);
     ^~~~~~~~~~~~~~~~~~~~~~~~
    CC      src/h1_htx.o

Let's apply the usual tricks to shut them up. No backport is needed.
2021-01-22 15:58:26 +01:00
Willy Tarreau
2bfce7e424 MINOR: debug: let ha_dump_backtrace() dump a bit further for some callers
The dump state is now passed to the function so that the caller can adjust
the behavior. A new series of 4 values allow to stop *after* dumping main
instead of before it or any of the usual loops. This allows to also report
BUG_ON() that could happen very high in the call graph (e.g. startup, or
the scheduler itself) while still understanding what the call path was.
2021-01-22 14:48:34 +01:00
Willy Tarreau
5baf4fe31a MEDIUM: debug: now always print a backtrace on CRASH_NOW() and friends
The purpose is to enable the dumping of a backtrace on BUG_ON(). While
it's very useful to know that a condition was met, very often some
caller context is missing to figure how the condition could happen.
From now on, on systems featuring backtrace, a backtrace of the calling
thread will also be dumped to stderr in addition to the unexpected
condition. This will help users of DEBUG_STRICT as they'll most often
find this backtrace in their logs even if they can't find their core
file.

A new "debug dev bug" expert-mode CLI command was added to test the
feature.
2021-01-22 14:18:34 +01:00
Willy Tarreau
a8459b28c3 MINOR: debug: create ha_backtrace_to_stderr() to dump an instant backtrace
This function calls the ha_dump_backtrace() function with a locally
allocated buffer and sends the output slightly indented to fd #2. It's
meant to be used as an emergency backtrace dump.
2021-01-22 14:15:36 +01:00
Willy Tarreau
123fc9786a MINOR: debug: extract the backtrace dumping code to its own function
The backtrace dumping code was located into the thread dump function
but it looks particularly convenient to be able to call it to produce
a dump in other situations, so let's move it to its own function and
make sure it's called last in the function so that we can benefit from
tail merging to save one entry.
2021-01-22 13:52:41 +01:00
Willy Tarreau
2f1227eb3f MINOR: debug: always export the my_backtrace function
In order to simplify the code and remove annoying ifdefs everywhere,
let's always export my_backtrace() and make it adapt to the situation
and return zero if not supported. A small update in the thread dump
function was needed to make sure we don't use its results if it fails
now.
2021-01-22 12:12:29 +01:00
Willy Tarreau
3d4631fec6 BUG/MEDIUM: mux-h2: fix read0 handling on partial frames
Since commit aade4edc1 ("BUG/MEDIUM: mux-h2: Don't handle pending read0
too early on streams"), we've met a few cases where an early connection
close wouldn't be properly handled if some data were pending in a frame
header, because the test now considers the buffer's contents before
accepting to report the close, but given that frame headers or preface
are consumed at once, the buffer cannot make progress when it's stuck
at intermediary lengths.

In order to address this, this patch introduces two flags in the h2c
connection to store any reported shutdown and failed parsing. The idea
is that we cannot rely on conn_xprt_read0_pending() in the parser since
it wouldn't consider data pending in the buffer nor intermediary layers,
but we know for certain that after a read0 is reported by the transport
layer in presence of an RD_SH on the connection, no more progress will
be made there. This alone is not sufficient to decide to end processing,
we can only do this once these final data have been submitted to a parser.
Therefore, now when a parser fails on missing data, we check if a read0
has already been reported on this connection, and if so we set a new
END_REACHED flag on the connection to indicate a failure to process the
final data. The h2c_read0_pending() function now simply reports this
flag's status. This way we're certain that the input shutdown is only
considered after the demux attempted to parse the last frame.

Maybe over the long term the subscribe() API should be improved to
synchronously fail when trying to subscribe for an even that will not
happen. This may be an elegant solution that could possibly work across
multiple layers and even muxes, and be usable at a few specific places
where that's needed.

Given the patch above was backported as far as 2.0, this one should be
backported there as well. It is possible that the fcgi mux has the same
issue, but this was not analysed yet.

Thanks to Pierre Cheynier for providing detailed traces allowing to
quickly narrow the problem down, and to Olivier for his analysis.
2021-01-22 10:54:15 +01:00
Christopher Faulet
341064eb16 BUG/MINOR: stream: Don't update counters when TCP to H2 upgrades are performed
When a TCP to H2 upgrade is performed, the SF_IGNORE flag is set on the
stream before killing it. This happens when a TCP/SSL client connection is
routed to a HTTP backend and the h2 alpn detected. The SF_IGNORE flag was
added for this purpose, to skip some processing when the stream is aborted
before a mux upgrade. Some counters updates were skipped this way. But some
others are still updated.

Now, all counters update at the end of process_stream(), before releasing
the stream, are ignored if SF_IGNORE flag is set. Note this stream is
aborted because we switch from a mono-stream to a multi-stream
multiplexer. It works differently for TCP to H1 upgrades.

This patch should be backported as far as 2.0 after some observation period.
2021-01-22 09:06:34 +01:00
William Dauchy
b9577450ea MINOR: contrib/prometheus-exporter: use fill_fe_stats for frontend dump
use `stats_fill_fe_stats` when possible to avoid duplicating code; make
use of field selector to get the needed field only.

this should not introduce any difference of output.

Signed-off-by: William Dauchy <wdauchy@gmail.com>
2021-01-21 18:59:30 +01:00
William Dauchy
0ef54397b0 MEDIUM: stats: allow to select one field in stats_fill_fe_stats
prometheus approach requires to output all values for a given metric
name; meaning we iterate through all metrics, and then iterate in the
inner loop on all objects for this metric.
In order to allow more code reuse, adapt the stats API to be able to
select one field or fill them all otherwise.
From this patch it should be possible to remove most of the duplicate
code on prometheuse side for the frontend.

Signed-off-by: William Dauchy <wdauchy@gmail.com>
2021-01-21 18:59:30 +01:00
William Dauchy
defd15685e MINOR: stats: add new start time field
Another patch in order to try to reconciliate haproxy stats and
prometheus. Here I'm adding a proper start time field in order to make
proper use of uptime field.
That being done we can move the calculation in `fill_info`

Signed-off-by: William Dauchy <wdauchy@gmail.com>
2021-01-21 18:59:30 +01:00
William Dauchy
a8766cfad1 MINOR: stats: duplicate 3 fields in bytes in info
in order to prepare a possible merge of fields between haproxy stats and
prometheus, duplicate 3 fields:
  INF_MEMMAX
  INF_POOL_ALLOC
  INF_POOL_USED
Those were specifically named in MB unit which is not what prometheus
recommends. We therefore used them but changed the unit while doing the
calculation. It created a specific case for that, up to the description.
This patch:
- removes some possible confusion, i.e. using MB field for bytes
- will permit an easier merge of fields such as description

First consequence for now, is that we can remove the calculation on
prometheus side and move it on `fill_info`.

Signed-off-by: William Dauchy <wdauchy@gmail.com>
2021-01-21 18:59:30 +01:00
Christopher Faulet
1d2d77b27f MEDIUM: mux-h1: Return a 501-not-implemented for upgrade requests with a body
If an HTTP protocol upgrade request with a payload is received, a
501-not-implemented error is now returned to the client. It is valid from
the RFC point of view but will be incompatible with the way the H2
websockets will be handled by HAProxy. And it is probably a very uncommon
way to do perform protocol upgrades.
2021-01-21 15:21:12 +01:00
Christopher Faulet
2eed800d54 MINOR: mux-h1: Be prepared to return 501-not-implemented error during parsing
With this patch, the H1 mux is now able to return 501-not-implemented errors
to client during the request parsing. However, no such errors are returned
for now.
2021-01-21 15:21:12 +01:00
Christopher Faulet
142dd33912 MINOR: muxes: Add exit status for errors about not implemented features
The MUX_ES_NOTIMPL_ERR exit status is added to allow the multiplexers to
report errors about not implemented features. This will be used by the H1
mux to return 501-not-implemented errors.
2021-01-21 15:21:12 +01:00
Christopher Faulet
e095f31d36 MINOR: http: Add HTTP 501-not-implemented error message
Add the support for the 501-not-implemented status code with the
corresponding default message. The documentation is updated accordingly
because it is now part of status codes HAProxy may emit via an errorfile or
a deny/return HTTP action.
2021-01-21 15:21:12 +01:00
Christopher Faulet
7d013e796c BUG/MEDIUM: mux-h2: Xfer rxbuf to the upper layer when creating a front stream
Just like the H1 muliplexer, when a new frontend H2 stream is created, the
rxbuf is xferred to the stream at the upper layer.

Originally, it is not a bug fix, but just an api standardization. And in
fact, it fixes a crash when a h2 stream is aborted after the request parsing
but before the first call to process_stream(). It crashes since the commit
8bebd2fe5 ("MEDIUM: http-ana: Don't process partial or empty request
anymore"). It is now totally unexpected to have an HTTP stream without a
valid request. But here the stream is unable to get the request because the
client connection was aborted. Passing it during the stream creation fixes
the bug. But the true problem is that the stream-interfaces are still
relying on the connection state while only the muxes should do so.

This fix is specific for 2.4. No backport needed.
2021-01-21 15:21:12 +01:00
Christopher Faulet
8f100427c4 BUG/MEDIUM: tcpcheck: Don't destroy connection in the wake callback context
When a tcpcheck ruleset uses multiple connections, the existing one must be
closed and destroyed before openning the new one. This part is handled in
the tcpcheck_main() function, when called from the wake callback function
(wake_srv_chk). But it is indeed a problem, because this function may be
called from the mux layer. This means a mux may call the wake callback
function of the data layer, which may release the connection and the mux. It
is easy to see how it is hazardous. And actually, depending on the
scheduling, it leads to crashes.

Thus, we must avoid to release the connection in the wake callback context,
and move this part in the check's process function instead. To do so, we
rely on the CHK_ST_CLOSE_CONN flags. When a connection must be replaced by a
new one, this flag is set on the check, in tcpcheck_main() function, and the
check's task is woken up. Then, the connection is really closed in
process_chk_conn() function.

This patch must be backported as far as 2.2, with some adaptations however
because the code is not exactly the same.
2021-01-21 15:21:12 +01:00
Bertrand Jacquin
25439de181 BUG/MINOR: mworker: define _GNU_SOURCE for strsignal()
glibc < 2.10 requires _GNU_SOURCE in order to make use of strsignal(),
otherwise leading to SEGV at runtime.

  $ make V=1 TARGET=linux-glibc-legacy USE_THREAD= USE_ACCEPT4=
  ..
  src/mworker.c: In function 'mworker_catch_sigchld':
  src/mworker.c:285: warning: implicit declaration of function 'strsignal'
  src/mworker.c:285: warning: pointer/integer type mismatch in conditional expression
  ..

  $ make V=1 reg-tests REGTESTS_TYPES=slow,default
  ..
  ###### Test case: reg-tests/mcli/mcli_start_progs.vtc ######
  ## test results in: "/tmp/haregtests-2021-01-19_15-18-07.n24989/vtc.29077.28f6153d"
  ---- h1    Bad exit status: 0x008b exit 0x0 signal 11 core 128
  ---- h1    Assert error in haproxy_wait(), src/vtc_haproxy.c line 792:  Condition(*(&h->fds[1]) >= 0) not true.  Errno=0 Success
  ..

  $ gdb ./haproxy /tmp/core.0.haproxy.30270
  ..
  Core was generated by `/root/haproxy/haproxy -d -W -S fd@8 -dM -f /tmp/haregtests-2021-01-19_15-18-07.'.
  Program terminated with signal 11, Segmentation fault.
  #0  0x00002aaaab387a10 in strlen () from /lib64/libc.so.6
  (gdb) bt
  #0  0x00002aaaab387a10 in strlen () from /lib64/libc.so.6
  #1  0x00002aaaab354b69 in vfprintf () from /lib64/libc.so.6
  #2  0x00002aaaab37788a in vsnprintf () from /lib64/libc.so.6
  #3  0x00000000004a76a3 in memvprintf (out=0x7fffedc680a0, format=0x5a5d58 "Current worker #%d (%d) exited with code %d (%s)\n", orig_args=0x7fffedc680d0)
      at src/tools.c:3868
  #4  0x00000000004bbd40 in print_message (label=0x58abed "ALERT", fmt=0x5a5d58 "Current worker #%d (%d) exited with code %d (%s)\n", argp=0x7fffedc680d0)
      at src/log.c:1066
  #5  0x00000000004bc07f in ha_alert (fmt=0x5a5d58 "Current worker #%d (%d) exited with code %d (%s)\n") at src/log.c:1109
  #6  0x0000000000534b7b in mworker_catch_sigchld (sh=<value optimized out>) at src/mworker.c:293
  #7  0x0000000000556af3 in __signal_process_queue () at src/signal.c:88
  #8  0x00000000004f6216 in signal_process_queue () at include/haproxy/signal.h:39
  #9  run_poll_loop () at src/haproxy.c:2859
  #10 0x00000000004f63b7 in run_thread_poll_loop (data=<value optimized out>) at src/haproxy.c:3028
  #11 0x00000000004faaac in main (argc=<value optimized out>, argv=0x7fffedc68498) at src/haproxy.c:904

See: https://man7.org/linux/man-pages/man3/strsignal.3.html

Must be backported as far as 2.0.
2021-01-21 12:16:52 +01:00
Willy Tarreau
0c0c0a2878 MINOR: mux-h1/show_fd: report as suspicious an entry with too many calls
An FD entry that maps to an H1 connection whose stream was woken
up more than 1M times is now flagged as suspicious.
2021-01-21 09:18:25 +01:00
Willy Tarreau
06bf83e0ae MINOR: mux-h2/show_fd: report as suspicious an entry with too many calls
An FD entry that maps to an H2C connection whose last stream was woken
up more than 1M times is now flagged as suspicious.
2021-01-21 09:17:42 +01:00
Willy Tarreau
4bd5d630ac MINOR: ssl/show_fd: report some FDs as suspicious when possible
If a subscriber's tasklet was called more than one million times, if
the ssl_ctx's connection doesn't match the current one, or if the
connection appears closed in one direction while the SSL stack is
still subscribed, the FD is reported as suspicious. The close cases
may occasionally trigger a false positive during very short and rare
windows. Similarly the 1M calls will trigger after 16GB are transferred
over a given connection. These are rare enough events to be reported as
suspicious.
2021-01-21 09:09:05 +01:00
Willy Tarreau
dacfde4ba4 MINOR: cli/show_fd: report some easily detectable suspicious states
A file descriptor which maps to a connection but has more than one
thread in its mask, or an FD handle that doesn't correspond to the FD,
or wiht no mux context, or an FD with no thread in its mask, or with
more than 1 million events is flagged as suspicious.
2021-01-21 09:09:05 +01:00
Willy Tarreau
8050efeacb MINOR: cli: give the show_fd helpers the ability to report a suspicious entry
Now the show_fd helpers at the transport and mux levels return an integer
which indicates whether or not the inspected entry looks suspicious. When
an entry is reported as suspicious, "show fd" will suffix it with an
exclamation mark ('!') in the dump, that is supposed to help detecting
them.

For now, helpers were adjusted to adapt to the new API but none of them
reports any suspicious entry yet.
2021-01-21 08:58:15 +01:00
Willy Tarreau
1776ffb975 MINOR: mux-fcgi: make the "show fd" helper also decode the fstrm subscriber when known
When dumping a live fcgi stream, also take the opportunity for reporting
the subscriber including the event, tasklet, handler and context.
2021-01-20 17:17:40 +01:00
Willy Tarreau
150c4f8b72 MINOR: mux-h1: make the "show fd" helper also decode the h1s subscriber when known
When dumping a live h1 stream, also take the opportunity for reporting
the subscriber including the event, tasklet, handler and context. Example:

   3030 : st=0x21(R:rA W:Ra) ev=0x04(heOpi) [Lc] tmask=0x4 umask=0x0 owner=0x7f97805c1f70 iocb=0x65b847(sock_conn_iocb) back=1 cflg=0x00002300 sv=s1/recv mux=H1 ctx=0x7f97805c21b0 h1c.flg=0x80000200 .sub=1 .ibuf=0@(nil)+0/0 .obuf=0@(nil)+0/0 h1s=0x7f97805c2380 h1s.flg=0x4010 .req.state=MSG_DATA .res.state=MSG_RPBEFORE .meth=POST status=0 .cs.flg=0x00000000 .cs.data=0x7f97805c1720 .subs=0x7f97805c1748(ev=1 tl=0x7f97805c1990 tl.calls=2 tl.ctx=0x7f97805c1720 tl.fct=si_cs_io_cb) xprt=RAW
2021-01-20 17:17:40 +01:00
Willy Tarreau
98e40b9818 MINOR: mux-h2: make the "show fd" helper also decode the h2s subscriber when known
When dumping a valid h2 stream, also dump the subscriber, its events,
tasklet context and handler. Example:

    128 : st=0x21(R:rA W:Ra) ev=0x01(heopI) [lc] tmask=0x1 umask=0x0 owner=0x7f40380d7370 iocb=0x65b71b(sock_conn_iocb) back=0 cflg=0x00001300 fe=recv mux=H2 ctx=0x1ad23e0 h2c.st0=FRP .err=0 .maxid=3 .lastid=-1 .flg=0x10000 .nbst=2 .nbcs=2 .fctl_cnt=0 .send_cnt=0 .tree_cnt=2 .orph_cnt=0 .sub=1 .dsi=3 .dbuf=16366@0x1ea9380+16441/16448 .msi=-1 .mbuf=[1..1|32],h=[0@(nil)+0/0],t=[0@(nil)+0/0] last_h2s=0x20a8340 .id=3 .st=OPN .flg=0x4100 .rxbuf=0@(nil)+0/0 .cs=0x20a8440(.flg=0x00100000 .data=0x20a8738) .subs=0x20a8760(ev=1 tl=0x20a89b0 tl.calls=22 tl.ctx=0x20a8738 tl.fct=si_cs_io_cb) xprt=SSL xprt_ctx=0x1aaf4c0 xctx.st=0 .xprt=RAW .wait.ev=1 .subs=0x1ad28e0(ev=1 tl=0x1ab3c70 tl.calls=176 tl.ctx=0x1ad23e0 tl.fct=h2_io_cb) .sent_early=0 .early_in=0
2021-01-20 17:17:39 +01:00
Willy Tarreau
691d503896 MINOR: xprt/mux: export all *_io_cb functions so that "show fd" resolves them
In FD dumps it's often very important to figure what upper layer function
is going to be called. Let's export the few I/O callbacks that appear as
tasklet functions so that "show fd" can resolve them instead of printing
a pointer relative to main. For example:

   1028 : st=0x21(R:rA W:Ra) ev=0x01(heopI) [lc] tmask=0x2 umask=0x2 owner=0x7f00b889b200 iocb=0x65b638(sock_conn_iocb) back=0 cflg=0x00001300 fe=recv mux=H2 ctx=0x7f00c8824de0 h2c.st0=FRH .err=0 .maxid=795 .lastid=-1 .flg=0x0000 .nbst=0 .nbcs=0 .fctl_cnt=0 .send_cnt=0 .tree_cnt=0 .orph_cnt=0 .sub=1 .dsi=795 .dbuf=0@(nil)+0/0 .msi=-1 .mbuf=[1..1|32],h=[0@(nil)+0/0],t=[0@(nil)+0/0] xprt=SSL xprt_ctx=0x7f00c86d0750 xctx.st=0 .xprt=RAW .wait.ev=1 .subs=0x7f00c88252e0(ev=1 tl=0x7f00a07d1aa0 tl.calls=1047 tl.ctx=0x7f00c8824de0 tl.fct=h2_io_cb) .sent_early=0 .early_in=0
2021-01-20 17:17:39 +01:00
Willy Tarreau
de5675a38c MINOR: ssl: provide a "show fd" helper to report important SSL information
The SSL context contains a lot of important details that are currently
missing from debug outputs. Now that we detect ssl_sock, we can perform
some sanity checks, print the next xprt, the subscriber callback's context,
handler and number of calls. The process function is also resolved. This
now gives for example on an H2 connection:

   1029 : st=0x21(R:rA W:Ra) ev=0x01(heopI) [lc] tmask=0x2 umask=0x2 owner=0x7fc714881700 iocb=0x65b528(sock_conn_iocb) back=0 cflg=0x00001300 fe=recv mux=H2 ctx=0x7fc734545e50 h2c.st0=FRH .err=0 .maxid=217 .lastid=-1 .flg=0x0000 .nbst=0 .nbcs=0 .fctl_cnt=0 .send_cnt=0 .tree_cnt=0 .orph_cnt=0 .sub=1 .dsi=217 .dbuf=0@(nil)+0/0 .msi=-1 .mbuf=[1..1|32],h=[0@(nil)+0/0],t=[0@(nil)+0/0] xprt=SSL xprt_ctx=0x7fc73478f230 xctx.st=0 .xprt=RAW .wait.ev=1 .subs=0x7fc734546350(ev=1 tl=0x7fc7346702e0 tl.calls=278 tl.ctx=0x7fc734545e50 tl.fct=main-0x144efa) .sent_early=0 .early_in=0
2021-01-20 17:17:39 +01:00
Willy Tarreau
108a271049 MINOR: xprt: add a new show_fd() helper to complete some "show fd" dumps.
Just like we did for the muxes, now the transport layers will have the
ability to provide helpers to report more detailed information about their
internal context. When the helper is not known, the pointer continues to
be dumped as-is if it's not NULL. This way a transport with no context nor
dump function will not add a useless "xprt_ctx=(nil)" but the pointer will
be emitted if valid or if a helper is defined.
2021-01-20 17:17:39 +01:00
Willy Tarreau
37be953424 MINOR: cli: make "show fd" also report the xprt and xprt_ctx
These ones are definitely missing from some dumps, let's report them! We
print the xprt's name instead of its useless pointer, as well as its ctx
when xprt is not NULL.
2021-01-20 17:17:39 +01:00
Willy Tarreau
eb0595d039 CLEANUP: cli: make "show fd" use a const connection to access other fields
Over time the code has uglified, casting fdt.owner as a struct connection
for about everything. Let's have a const struct connection* there and take
this opportunity for passing all fields as const as well.

Additionally a misplaced closing parenthesis on the output was fixed.
2021-01-20 17:17:39 +01:00
Willy Tarreau
45fd1030d5 CLEANUP: tools: make resolve_sym_name() take a const pointer
When 0c439d895 ("BUILD: tools: make resolve_sym_name() return a const")
was written, the pointer argument ought to have been turned to const for
more flexibility. Let's do it now.
2021-01-20 17:17:39 +01:00
Willy Tarreau
ed4464e6c6 BUG/MINOR: mux_h2: missing space between "st" and ".flg" in the "show fd" helper
That was causing confusing outputs like this one whenan H2S is known:

   1030 : ... last_h2s=0x2ed8390 .id=775 .st=HCR.flg=0x4001 .rxbuf=...
                                                ^^^^

This was introduced by commit ab2ec4540 in 2.1-dev2 so the fix can be
backported as far as 2.1.
2021-01-20 17:17:39 +01:00
Frdric Lcaille
2b0ba54ddb BUG/MINOR: peers: Wrong "new_conn" value for "show peers" CLI command.
This counter could be hugely incremented by the peer task responsible of managing
peer synchronizations and reconnections, for instance when a peer is not reachable
there is a period where the appctx is not created. If we receive  stick-table
updates before the peer session (appctx) is instantiated, we reach the code
responsible of incrementing the "new_conn" counter.
With this patch we increment this counter only when we really instantiate a new
peer session thanks to peer_session_create().

May be backported as far as 2.0.
2021-01-19 10:08:18 +01:00
Tim Duesterhus
ed84d84a29 CLEANUP: Rename accept_encoding_hash_cmp to accept_encoding_bitmap_cmp
For the `accept-encoding` header a bitmap and not a hash is stored.
2021-01-18 15:01:48 +01:00
Tim Duesterhus
5897cfe18e CLEANUP: cache: Use proper data types in secondary_key_cmp()
- hash_length is `unsigned int` and so should offset.
- idx is compared to a `size_t` and thus it should also be.
2021-01-18 15:01:46 +01:00
Tim Duesterhus
1d66e396bf MINOR: cache: Remove the hash part of the accept-encoding secondary key
As of commit 6ca89162dc this hash no longer is
required, because unknown encodings are not longer stored and known encodings
do not use the cache.
2021-01-18 15:01:41 +01:00
Frdric Lcaille
4b1a05fcf8 BUG/MINOR: peers: Possible appctx pointer dereference.
This bug may occur when enabling peers traces. It is possible that
peer->appctx is NULL when entering peer_session_release().
2021-01-17 21:58:03 +01:00
Remi Tricot-Le Breton
6ca89162dc MINOR: cache: Do not store responses with an unknown encoding
If a server varies on the accept-encoding header and it sends a response
with an encoding we do not know (see parse_encoding_value function), we
will not store it. This will prevent unexpected errors caused by
cache collisions that could happen in accept_encoding_hash_cmp.
2021-01-15 22:33:05 +01:00
Adis Nezirovic
b62b78be13 BUG/MEDIUM: stats: add missing INF_BUILD_INFO definition
commit 5a982a7165 ("MINOR:
contrib/prometheus-exporter: export build_info") is breaking lua
`core.get_info()`.

This patch makes sure build_info is correctly initialised in all cases.

Reviewed-by: William Dauchy <wdauchy@gmail.com>
2021-01-15 18:47:19 +01:00
Willy Tarreau
81d7092dbd BUILD: peers: fix build warning about unused variable
Previous commit da2b0844f ("MINOR: peers: Add traces for peer control
messages.") introduced a build warning on some compiler versions after
the removal of variable "peers" in peer_send_msgs() because variable
"s" was used only to assign this one, and variable "si" to assign "s".
Let's remove both to fix the warning. No backport is needed.
2021-01-15 17:08:38 +01:00
Baptiste Assmann
6554742b15 BUG/MINOR: dns: SRV records ignores duplicated AR records (v2)
V2 of this fix which includes a missing pointer initialization which was
causing a segfault in v1 (949a7f6459)

This bug happens when a service has multiple records on the same host
and the server provides the A/AAAA resolution in the response as AR
(Additional Records).

In such condition, the first occurence of the host will be taken from
the Additional section, while the second (and next ones) will be process
by an independent resolution task (like we used to do before 2.2).
This can lead to a situation where the "synchronisation" of the
resolution may diverge, like described in github issue #971.

Because of this behavior, HAProxy mixes various type of requests to
resolve the full list of servers: SRV+AR for all "first" occurences and
A/AAAA for all other occurences of an existing hostname.
IE: with the following type of response:

   ;; ANSWER SECTION:
   _http._tcp.be2.tld.     3600    IN      SRV     5 500 80 A2.tld.
   _http._tcp.be2.tld.     3600    IN      SRV     5 500 86 A3.tld.
   _http._tcp.be2.tld.     3600    IN      SRV     5 500 80 A1.tld.
   _http._tcp.be2.tld.     3600    IN      SRV     5 500 85 A3.tld.

   ;; ADDITIONAL SECTION:
   A2.tld.                 3600    IN      A       192.168.0.2
   A3.tld.                 3600    IN      A       192.168.0.3
   A1.tld.                 3600    IN      A       192.168.0.1
   A3.tld.                 3600    IN      A       192.168.0.3

the first A3 host is resolved using the Additional Section and the
second one through a dedicated A request.

When linking the SRV records to their respective Additional one, a
condition was missing (chek if said SRV record is already attached to an
Additional one), leading to stop processing SRV only when the target
SRV field matches the Additional record name. Hence only the first
occurence of a target was managed by an additional record.
This patch adds a condition in this loop to ensure the record being
parsed is not already linked to an Additional Record. If so, we can
carry on the parsing to find a possible next one with the same target
field value.

backport status: 2.2 and above
2021-01-15 17:01:24 +01:00
Frdric Lcaille
da2b0844fc MINOR: peers: Add traces for peer control messages.
Display traces when sending/receiving peer control messages (synchronisation, heartbeat).
Add remaining traces when parsing malformed messages (acks, stick-table definitions)
or ignoring them.
Also add traces when releasing session or when reaching the PEER_SESS_ST_ERRPROTO
peer protocol state.
2021-01-15 16:57:17 +01:00
Willy Tarreau
dc2410d093 CLEANUP: pattern: rename pat_ref_commit() to pat_ref_commit_elt()
It's about the third time I get confused by these functions, half of
which manipulate the reference as a whole and those manipulating only
an entry. For me "pat_ref_commit" means committing the pattern reference,
not just an element, so let's rename it. A number of other ones should
really be renamed before 2.4 gets released :-/
2021-01-15 14:11:59 +01:00
David CARLIER
6a9060189d BUG/MINOR: threads: Fixes the number of possible cpus report for Mac.
There is no low level api to achieve same as Linux/FreeBSD, we rely
on CPUs available. Without this, the number of threads is just 1 for
Mac while having 8 cores in my M1.

Backporting to 2.1 should be enough if that's possible.

Signed-off-by: David CARLIER <devnexen@gmail.com>
2021-01-15 11:58:46 +01:00
Christopher Faulet
e3bdc81f8a MINOR: server: Forbid server definitions in frontend sections
An fatal error is now reported if a server is defined in a frontend
section. til now, a warning was just emitted and the server was ignored. The
warning was added in the 1.3.4 when the frontend/backend keywords were
introduced to allow a smooth transition and to not break existing
configs. It is old enough now to emit an fatal error in this case.

This patch is related to the issue #1043. It may be backported at least as
far as 2.2, and possibly to older versions. It relies on the previous commit
("MINOR: config: Add failifnotcap() to emit an alert on proxy capabilities").
2021-01-13 17:45:34 +01:00
Christopher Faulet
4e36682d51 BUG/MINOR: init: Use a dynamic buffer to set HAPROXY_CFGFILES env variable
The HAPROXY_CFGFILES env variable is built using a static trash chunk, via a
call to get_trash_chunk() function. This chunk is reserved during the whole
configuration parsing. It is far too large to guarantee it will not be
reused during the configuration parsing. And in fact, it happens in the lua
code since the commit f67442efd ("BUG/MINOR: lua: warn when registering
action, conv, sf, cli or applet multiple times"), when a lua script is
loaded.

To fix the bug, we now use a dynamic buffer instead. And we call memprintf()
function to handle both the allocation and the formatting. Allocation errors
at this stage are fatal.

This patch should fix the issue #1041. It must be backported as far as 2.0.
2021-01-13 17:45:25 +01:00
William Dauchy
5d9b8f3c93 MINOR: contrib/prometheus-exporter: use fill_info for process dump
use `stats_fill_info` when possible to avoid duplicating code.

Signed-off-by: William Dauchy <wdauchy@gmail.com>
2021-01-13 15:19:00 +01:00
Jerome Magnin
50f757c5fd BUG/MINOR: init: enforce strict-limits when using master-worker
The strict-limits global option was introduced with commit 0fec3ab7b
("MINOR: init: always fail when setrlimit fails"). When used in
conjuction with master-worker, haproxy will not fail when a setrlimit
fails. This happens because we only exit() if master-worker isn't used.

This patch removes all tests for master-worker mode for all cases covered
by strict-limits scope.

This should be backported from 2.1 onward.
This should fix issue #1042.

Reviewed by William Dauchy <wdauchy@gmail.com>
2021-01-13 13:17:11 +01:00
Christopher Faulet
6ecd59326f BUG/MINOR: check: Don't perform any check on servers defined in a frontend
If a server is defined in a frontend, thus a proxy without the backend
capability, the 'check' and 'agent-check' keywords are ignored. This way, no
check is performed on an ignored server. This avoids a segfault because some
part of the tcpchecks are not fully initialized (or released for frontends
during the post-check).

In addition, an test on the server's proxy capabilities is performed when
checks or agent-checks are initialized and nothing is performed for servers
attached to a non-backend proxy.

This patch should fix the issue #1043. It must be backported as far as 2.2.
2021-01-12 17:55:22 +01:00
Remi Tricot-Le Breton
22e0d9b39c BUG/MINOR: sample: Memory leak of sample_expr structure in case of error
If an errors occurs during the sample expression parsing, the alloced
sample_expr is not freed despite having its main pointer reset.

This fixes GitHub issue #1046.
It could be backported as far as 1.8.
2021-01-12 17:00:59 +01:00
Christopher Faulet
a1eea3bbb1 Revert "BUG/MINOR: dns: SRV records ignores duplicated AR records"
This reverts commit 949a7f6459.

The first part of the patch introduces a bug. When a dns answer item is
allocated, its <ar_item> is only initialized at the end of the parsing, when
the item is added in the answer list. Thus, we must not try to release it
during the parsing.

The second part is also probably buggy. It fixes the issue #971 but reverts
a fix for the issue #841 (see commit fb0884c8297 "BUG/MEDIUM: dns: Don't
store additional records in a linked-list"). So it must be at least
revalidated.

This revert fixes a segfault reported in a comment of the issue #971. It
must be backported as far as 2.2.
2021-01-12 16:37:54 +01:00
William Dauchy
e997010acc BUG/MINOR: sample: check alloc_trash_chunk return value in concat()
like it is done in other places, check the return value of
`alloc_trash_chunk` before using it. This was detected by coverity.

this patch fixes commit 591fc3a330
("BUG/MINOR: sample: fix concat() converter's corruption with non-string
variables"
As a consequence, this patch should be backported as far as 2.0

this should fix github issue #1039

Signed-off-by: William Dauchy <wdauchy@gmail.com>
2021-01-11 14:10:11 +01:00
William Dauchy
aabde71332 MINOR: reg-tests: add a way to add service dependency
I was looking at writing a simple first test for prometheus but I
realised there is no proper way to exclude it if haproxy was not built
with prometheus plugin.

Today we have `REQUIRE_OPTIONS` in reg-tests which is based on `Feature
list` from `haproxy -vv`. Those options are coming from the Makefile
itself.

A plugin is build this way:
  EXTRA_OBJS="contrib/prometheus-exporter/service-prometheus.o"

It does register service actions through `service_keywords_register`.
Those are listed through `list_services` in `haproxy -vv`.
To facilitate parsing, I slightly changed the output to a single line
and integrate it in regtests shell script so that we can now specify a
dependency while writing a reg-test for prometheus, e.g:

  #REQUIRE_SERVICE=prometheus-exporter
  #REQUIRE_SERVICES=prometheus-exporter,foo

There might be other ways to handle this, but that's the cleanest I
found; I understand people might be concerned by this output change in
`haproxy -vv` which goes from:

  Available services :
          foo
          bar

to:

  Available services : foo bar

Signed-off-by: William Dauchy <wdauchy@gmail.com>
2021-01-10 07:42:33 +01:00
William Dauchy
5417e898ff CLEANUP: sample: remove uneeded check in json validation
- check functions are never called with a NULL args list, it is always
  an array, so first check can be removed
- the expression parser guarantees that we can't have anything else,
  because we mentioned json converter takes a mandatory string argument.
  Thus test on `ARGT_STR` can be removed as well
- also add breaking line between enum and function declaration

In order to validate it, add a simple json test testing very simple
cases but can be improved in the future:

- default json converter without args
- json converter failing on error (utf8)
- json converter with error being removed (utf8s)

Signed-off-by: William Dauchy <wdauchy@gmail.com>
2021-01-10 07:39:58 +01:00
Thayne McCombs
4fb255df03 BUG/MINOR: server: Memory leak of proxy.used_server_addr during deinit
GitHub Issue #1037 Reported a memory leak in deinit() caused by an
allocation made in sa2str() that was stored in srv_set_addr_desc().

When destroying each server for a proxy in deinit, include freeing the
memory in the key of server->addr_node.

The leak was introduced in commit 92149f9a8 ("MEDIUM: stick-tables: Add
srvkey option to stick-table") which is not in any released version so
no backport is needed.

Cc: Tim Duesterhus <tim@bastelstu.be>
2021-01-10 07:22:15 +01:00
Willy Tarreau
591fc3a330 BUG/MINOR: sample: fix concat() converter's corruption with non-string variables
Patrick Hemmer reported that calling concat() with an integer variable
causes a %00 to appear at the beginning of the output. Looking at the
code, it's not surprising. The function uses get_trash_chunk() to get
one of the trashes, but can call casting functions which will also use
their trash in turn and will cycle back to ours, causing the trash to
be overwritten before being assigned to a sample.

By allocating the trash from a pool using alloc_trash_chunk(), we can
avoid this. However we must free it so the trash's contents must be
moved to a permanent trash buffer before returning. This is what's
achieved using smp_dup().

This should be backported as far as 2.0.
2021-01-08 16:08:43 +01:00
Thayne McCombs
8f0cc5c4ba CLEANUP: Fix spelling errors in comments
This is from the output of codespell. It's done at once over a bunch
of files and only affects comments, so there is nothing user-visible.
No backport needed.
2021-01-08 14:56:32 +01:00
Tim Duesterhus
22586524e3 BUG/MINOR: hlua: Fix memory leak in hlua_alloc
During a configuration check valgrind reports:

    ==14425== 0 bytes in 106 blocks are definitely lost in loss record 1 of 107
    ==14425==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==14425==    by 0x4C2FDEF: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==14425==    by 0x443CFC: hlua_alloc (hlua.c:8662)
    ==14425==    by 0x5F72B11: luaM_realloc_ (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
    ==14425==    by 0x5F78089: luaH_free (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
    ==14425==    by 0x5F707D3: sweeplist (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
    ==14425==    by 0x5F710D0: luaC_freeallobjects (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
    ==14425==    by 0x5F7715D: close_state (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
    ==14425==    by 0x443D4C: hlua_deinit (hlua.c:9302)
    ==14425==    by 0x543F88: deinit (haproxy.c:2742)
    ==14425==    by 0x5448E7: deinit_and_exit (haproxy.c:2830)
    ==14425==    by 0x5455D9: init (haproxy.c:2044)

This is due to Lua calling `hlua_alloc()` with `ptr = NULL` and `nsize = 0`.
While `realloc` is supposed to be equivalent `free()` if the size is `0` this
is only required for a non-NULL pointer. Apparently my allocator (or valgrind)
actually allocates a zero size area if the pointer is NULL, possibly taking up
some memory for management structures.

Fix this leak by specifically handling the case where both the pointer and the
size are `0`.

This bug appears to have been introduced with the introduction of the
multi-threaded Lua, thus this fix is specific for 2.4. No backport needed.
2021-01-08 14:46:43 +01:00
Ilya Shipitsin
76837bc948 CLEANUP: cfgparse: replace "realloc" with "my_realloc2" to fix to memory leak on error
my_realloc2 frees variable in case of allocation failure.

fixes #1030

realloc was introduced in 9e1758efbd

this might be backported to 2.2, 2.3
2021-01-08 14:45:39 +01:00
Ilya Shipitsin
761d64c7ae BUILD: ssl: guard openssl specific with SSL_READ_EARLY_DATA_SUCCESS
let us switch to SSL_READ_EARLY_DATA_SUCCESS instead of openssl versions
2021-01-07 10:20:04 +01:00
Ilya Shipitsin
ec36c91c69 BUILD: ssl: guard EVP_PKEY_get_default_digest_nid with ASN1_PKEY_CTRL_DEFAULT_MD_NID
let us switch to openssl specific macro instead of versions
2021-01-07 10:20:00 +01:00
Ilya Shipitsin
2aa4b3a083 BUILD: SSL: guard TLS13 ciphersuites with HAVE_SSL_CTX_SET_CIPHERSUITES
accidently src/server.c still used earlier guarding
2021-01-07 10:19:56 +01:00
William Dauchy
888b0ae8cf MINOR: converter: adding support for url_enc
add base support for url encode following RFC3986, supporting `query`
type only.

- add test checking url_enc/url_dec/url_enc
- update documentation
- leave the door open for future changes

this should resolve github issue #941

Signed-off-by: William Dauchy <wdauchy@gmail.com>
2021-01-06 23:43:04 +01:00
Willy Tarreau
421ed3952d [RELEASE] Released version 2.4-dev5
Released version 2.4-dev5 with the following main changes :
    - BUG/MEDIUM: mux_h2: Add missing braces in h2_snd_buf()around trace+wakeup
    - BUILD: hpack: hpack-tbl-t.h uses VAR_ARRAY but does not include compiler.h
    - MINOR: time: increase the minimum wakeup interval to 60s
    - MINOR: check: do not ignore a connection header for http-check send
    - REGTESTS: complete http-check test
    - CI: travis-ci: drop coverity scan builds
    - MINOR: atomic: don't use ; to separate instruction on aarch64.
    - IMPORT: xxhash: update to v0.8.0 that introduces stable XXH3 variant
    - MEDIUM: xxhash: use the XXH3 functions to generate 64-bit hashes
    - MEDIUM: xxhash: use the XXH_INLINE_ALL macro to inline all functions
    - CLEANUP: xxhash: remove the unused src/xxhash.c
    - MINOR: sample: add the xxh3 converter
    - REGTESTS: add tests for the xxh3 converter
    - MINOR: protocol: Create proto_quic QUIC protocol layer.
    - MINOR: connection: Attach a "quic_conn" struct to "connection" struct.
    - MINOR: quic: Redefine control layer callbacks which are QUIC specific.
    - MINOR: ssl_sock: Initialize BIO and SSL objects outside of ssl_sock_init()
    - MINOR: connection: Add a new xprt to connection.
    - MINOR: ssl: Export definitions required by QUIC.
    - MINOR: cfgparse: Do not modify the QUIC xprt when parsing "ssl".
    - MINOR: tools: Add support for QUIC addresses parsing.
    - MINOR: quic: Add definitions for QUIC protocol.
    - MINOR: quic: Import C source code files for QUIC protocol.
    - MINOR: listener: Add QUIC info to listeners and receivers.
    - MINOR: server: Add QUIC definitions to servers.
    - MINOR: ssl: SSL CTX initialization modifications for QUIC.
    - MINOR: ssl: QUIC transport parameters parsing.
    - MINOR: quic: QUIC socket management finalization.
    - MINOR: cfgparse: QUIC default server transport parameters init.
    - MINOR: quic: Enable the compilation of QUIC modules.
    - MAJOR: quic: Make usage of ebtrees to store QUIC ACK ranges.
    - MINOR: quic: Attempt to make trace more readable
    - MINOR: quic: Make usage of the congestion control window.
    - MINOR: quic: Flag RX packet as ack-eliciting from the generic parser.
    - MINOR: quic: Code reordering to help in reviewing/modifying.
    - MINOR: quic: Add traces to congestion avoidance NewReno callback.
    - MINOR: quic: Display the SSL alert in ->ssl_send_alert() callback.
    - MINOR: quic: Update the initial salt to that of draft-29.
    - MINOR: quic: Add traces for in flght ack-eliciting packet counter.
    - MINOR: quic: make a packet build fails when qc_build_frm() fails.
    - MINOR: quic: Add traces for quic_packet_encrypt().
    - MINOR: cache: Refactoring of secondary_key building functions
    - MINOR: cache: Avoid storing responses whose secondary key was not correctly calculated
    - BUG/MINOR: cache: Manage multiple headers in accept-encoding normalization
    - MINOR: cache: Add specific secondary key comparison mechanism
    - MINOR: http: Add helper functions to trim spaces and tabs
    - MEDIUM: cache: Manage a subset of encodings in accept-encoding normalizer
    - REGTESTS: cache: Simplify vary.vtc file
    - REGTESTS: cache: Add a specific test for the accept-encoding normalizer
    - MINOR: cache: Remove redundant test in http_action_req_cache_use
    - MINOR: cache: Replace the "process-vary" option's expected values
    - CI: GitHub Actions: enable daily Coverity scan
    - BUG/MEDIUM: cache: Fix hash collision in `accept-encoding` handling for `Vary`
    - MEDIUM: stick-tables: Add srvkey option to stick-table
    - REGTESTS: add test for stickiness using "srvkey addr"
    - BUILD: Makefile: disable -Warray-bounds until it's fixed in gcc 11
    - BUG/MINOR: sink: Return an allocation failure in __sink_new if strdup() fails
    - BUG/MINOR: lua: Fix memory leak error cases in hlua_config_prepend_path
    - MINOR: lua: Use consistent error message 'memory allocation failed'
    - CLEANUP: Compare the return value of `XXXcmp()` functions with zero
    - CLEANUP: Apply the coccinelle patch for `XXXcmp()` on include/
    - CLEANUP: Apply the coccinelle patch for `XXXcmp()` on contrib/
    - MINOR: qpack: Add static header table definitions for QPACK.
    - CLEANUP: qpack: Wrong comment about the draft for QPACK static header table.
    - CLEANUP: quic: Remove useless QUIC event trace definitions.
    - BUG/MINOR: quic: Possible CRYPTO frame building errors.
    - MINOR: quic: Pass quic_conn struct to frame parsers.
    - BUG/MINOR: quic: Wrong STREAM frames parsing.
    - MINOR: quic: Drop packets with STREAM frames with wrong direction.
    - CLEANUP: ssl: Remove useless loop in tlskeys_list_get_next()
    - CLEANUP: ssl: Remove useless local variable in tlskeys_list_get_next()
    - MINOR: ssl: make tlskeys_list_get_next() take a list element
    - Revert "BUILD: Makefile: disable -Warray-bounds until it's fixed in gcc 11"
    - BUG/MINOR: cfgparse: Fail if the strdup() for `rule->be.name` for `use_backend` fails
    - CLEANUP: mworker: remove duplicate pointer tests in cfg_parse_program()
    - CLEANUP: Reduce scope of `header_name` in http_action_store_cache()
    - CLEANUP: Reduce scope of `hdr_age` in http_action_store_cache()
    - CLEANUP: spoe: fix typo on `var_check_arg` comment
    - BUG/MINOR: tcpcheck: Report a L7OK if the last evaluated rule is a send rule
    - CI: github actions: build several popular "contrib" tools
    - DOC: Improve the message printed when running `make` w/o `TARGET`
    - BUG/MEDIUM: server: srv_set_addr_desc() crashes when a server has no address
    - REGTESTS: add unresolvable servers to srvkey-addr
    - BUG/MINOR: stats: Make stat_l variable used to dump a stat line thread local
    - BUG/MINOR: quic: NULL pointer dereferences when building post handshake frames.
    - SCRIPTS: improve announce-release to support different tag and versions
    - SCRIPTS: make announce release support preparing announces before tag exists
    - CLEANUP: assorted typo fixes in the code and comments
    - BUG/MINOR: srv: do not init address if backend is disabled
    - BUG/MINOR: srv: do not cleanup idle conns if pool max is null
    - CLEANUP: assorted typo fixes in the code and comments
    - CLEANUP: few extra typo and fixes over last one ("ot" -> "to")
2021-01-06 17:41:32 +01:00
Willy Tarreau
94a01e1cb7 CLEANUP: few extra typo and fixes over last one ("ot" -> "to")
As noticed by Tim there were a few incorrect fixes in the previous patch
("ot" -> "to" and not "or").
2021-01-06 17:35:52 +01:00
Ilya Shipitsin
b8888ab557 CLEANUP: assorted typo fixes in the code and comments
This is 15th iteration of typo fixes
2021-01-06 17:32:03 +01:00
Amaury Denoyelle
10d5c3172b BUG/MINOR: srv: do not cleanup idle conns if pool max is null
If a server is configured to not have any idle conns, returns immediatly
from srv_cleanup_connections. This avoids a segfault when a server is
configured with pool-max-conn to 0.

This should be backported up to 2.2.
2021-01-06 16:57:17 +01:00
Amaury Denoyelle
e3c4192962 BUG/MINOR: srv: do not init address if backend is disabled
Do not proceed on init_addr if the backend of the server is marked as
disabled. When marked as disabled, the server is not fully initialized
and some operation must be avoided to prevent segfault. It is correct
because there is no way to activate a disabled backend.

This fixes the github issue #1031.
This should be backported to 2.2.
2021-01-06 16:57:17 +01:00
Ilya Shipitsin
1e9a66603f CLEANUP: assorted typo fixes in the code and comments
This is 14th iteration of typo fixes
2021-01-06 16:26:50 +01:00
Frdric Lcaille
153d4a89d0 BUG/MINOR: quic: NULL pointer dereferences when building post handshake frames.
The second one was detected by cppcheck contrary to the first one.
Fixes issue #1032.
Thank you to Ilya for having reported this.
2021-01-06 13:59:05 +01:00
Christopher Faulet
de79cd28ec BUG/MINOR: stats: Make stat_l variable used to dump a stat line thread local
Since ee63d4bd6 ("MEDIUM: stats: integrate static proxies stats in new
stats"), all dumped stats for a given domain, the default ones and the
modules ones, are merged in a signle array to dump them in a generic way.
For this purpose, the stat_l global variable is allocated at startup to
store a line of stats before the dump, i.e. all stats of an entity
(frontend, backend, listener, server or dns nameserver). But this variable
is not thread safe.  If stats are retrieved concurrently by several clients
on different threads, the same variable is used. This leads to corrupted
stats output.

To fix the bug, the stat_l variable is now thread local.

This patch should probably solve issues #972 and #992. It must be backported
to 2.3.
2021-01-06 10:34:12 +01:00
Thayne McCombs
24da7e1aa6 BUG/MEDIUM: server: srv_set_addr_desc() crashes when a server has no address
GitHub Issue #1026 reported a crash during configuration check for the
following example config:

    backend 0
    server 0 0
    server 0 0

HAProxy crashed in srv_set_addr_desc() due to a NULL pointer dereference
caused by `sa2str` returning NULL for an `AF_UNSPEC` address (`0`).

Check to make sure the address key is non-null before using it for
comparison or inserting it into the tree.

The crash was introduced in commit 92149f9a8 ("MEDIUM: stick-tables: Add
srvkey option to stick-table") which not in any released version so no
backport is needed.

Cc: Tim Duesterhus <tim@bastelstu.be>
2021-01-06 09:19:15 +01:00
Christopher Faulet
8d4977ae86 BUG/MINOR: tcpcheck: Report a L7OK if the last evaluated rule is a send rule
When all rules of a tcpcheck ruleset are successfully evaluated, the right
check status must always be reported. It is true if the last evaluated rule
is an expect or a connect rule. But not if it is a send rule. In this
situation, nothing more is done until the check timeout expiration and a
L7TOUT is reported instead of a L7OK.

Now, by default, when all rules were successfully evaluated, a L7OK is
reported. When the last evaluated rule is an expect or a connect, the
behavior remains unchanged.

This patch should fix the issue #1027. It must be backported as far as 2.2.
2021-01-05 17:31:49 +01:00
William Dauchy
afb9368221 CLEANUP: spoe: fix typo on var_check_arg comment
there was an extra `s` added to the `var_check_arg` function

Signed-off-by: William Dauchy <wdauchy@gmail.com>
2021-01-05 17:23:32 +01:00
Tim Duesterhus
c294284e33 CLEANUP: Reduce scope of hdr_age in http_action_store_cache()
This is only required to process the `age` header.
2021-01-05 17:05:58 +01:00
Tim Duesterhus
e2fff10a19 CLEANUP: Reduce scope of header_name in http_action_store_cache()
This variable is only needed deeply nested in a single location and clang's
static analyzer complains about a dead initialization. Reduce the scope to
satisfy clang and the human that reads the function.
2021-01-05 17:05:58 +01:00
Willy Tarreau
8f7efcddd6 CLEANUP: mworker: remove duplicate pointer tests in cfg_parse_program()
As reported in issue #1017, there are two harmless duplicate tests in
cfg_parse_program(), one made of a "if" using the same condition as the
loop it's in, and the other one being a null test before a free. This
just removes them. No backport is needed.
2021-01-05 15:58:37 +01:00
Tim Duesterhus
5ce5a1586d BUG/MINOR: cfgparse: Fail if the strdup() for rule->be.name for use_backend fails
This patch fixes GitHub issue #1024.

I could track the `strdup` back to commit
3a1f5fda10 which is 1.9-dev8. It's probably not
worth the effort to backport it across this refactoring.

This patch should be backported to 1.9+.
2021-01-05 11:37:41 +01:00
Willy Tarreau
b6fc524f05 MINOR: ssl: make tlskeys_list_get_next() take a list element
As reported in issue #1010, gcc-11 as of 2021-01-05 is overzealous in
its -Warray-bounds check as it considers that a cast of a global struct
accesses the entire struct even if only one specific element is accessed.
This instantly breaks all lists making use of container_of() to build
their iterators as soon as the starting point is known if the next
element is retrieved from the list head in a way that is visible to the
compiler's optimizer, because it decides that accessing the list's next
element dereferences the list as a larger struct (which it does not).

The temporary workaround consisted in disabling -Warray-bounds, but this
warning is traditionally quite effective at spotting real bugs, and we
actually have is a single occurrence of this issue in the whole code.

By changing the tlskeys_list_get_next() function to take a list element
as the starting point instead of the current element, we can avoid
the starting point issue but this requires to change all call places
to write hideous casts made of &((struct blah*)ref)->list. At the
moment we only have two such call places, the first one being used to
initialize the list (which is the one causing the warning) and which
is thus easy to simplify, and the second one for which we already have
an aliased pointer to the reference that is still valid at the call
place, and given the original pointer also remained unchanged, we can
safely use this alias, and this is safer than leaving a cast there.

Let's make this change now while it's still easy.

The generated code only changed in function cli_io_handler_tlskeys_files()
due to register allocation and the change of variable scope between the
old one and the new one.
2021-01-05 11:15:45 +01:00
Tim Duesterhus
cb8b281c02 CLEANUP: ssl: Remove useless local variable in tlskeys_list_get_next()
`getnext` was only used to fill `ref` at the beginning of the function. Both
have the same type. Replace the parameter name by `ref` to remove the useless
local variable.
2021-01-05 10:25:20 +01:00
Tim Duesterhus
2c7bb33144 CLEANUP: ssl: Remove useless loop in tlskeys_list_get_next()
This loop was always exited in the first iteration by `return`.
2021-01-05 10:24:36 +01:00
Frdric Lcaille
242fb1b639 MINOR: quic: Drop packets with STREAM frames with wrong direction.
A server initiates streams with odd-numbered stream IDs.
Also add useful traces when parsing STREAM frames.
2021-01-04 12:31:28 +01:00
Frdric Lcaille
129a351a3f BUG/MINOR: quic: Wrong STREAM frames parsing.
After having re-read the RFC, we noticed there are two bugs in the STREAM
frame parser. When the OFF bit (0x04) in the frame type is not set
we must set the offset to 0 (it was not set at all). When the LEN bit (0x02)
is not set we must extend the length of the data field to the end of the packet
(it was not set at all).
2021-01-04 12:31:28 +01:00
Frdric Lcaille
50044adc60 MINOR: quic: Pass quic_conn struct to frame parsers.
This is only for debugging purposes.
2021-01-04 12:31:28 +01:00
Frdric Lcaille
ea60499912 BUG/MINOR: quic: Possible CRYPTO frame building errors.
This is issue is due to the fact that when we call the function
responsible of building CRYPTO frames to fill a buffer, the Length
field of this packet did not take into an account the trailing 16 bytes for
the AEAD tag. Furthermore, the remaining <room> available in this buffer
was not decremented by the CRYPTO frame length, but only by the CRYPTO data length
of this frame.
2021-01-04 12:31:28 +01:00
Frdric Lcaille
6c1e36ce55 CLEANUP: quic: Remove useless QUIC event trace definitions.
Remove QUIC_EV_CONN_E* event trace macros which were defined for  errors.
Replace QUIC_EV_CONN_ECHPKT by QUIC_EV_CONN_BCFRMS used in qc_build_cfrms()
2021-01-04 12:31:28 +01:00
Frdric Lcaille
d341fc3609 CLEANUP: qpack: Wrong comment about the draft for QPACK static header table.
This came with a "copy and paste" from the definition for HPACK.
2021-01-04 12:31:28 +01:00
Frdric Lcaille
164096eb76 MINOR: qpack: Add static header table definitions for QPACK.
As HPACK, QPACK makes usage of a static header table.
2021-01-04 12:31:28 +01:00
Tim Duesterhus
e5ff14100a CLEANUP: Compare the return value of XXXcmp() functions with zero
According to coding-style.txt it is recommended to use:

`strcmp(a, b) == 0` instead of `!strcmp(a, b)`

So let's do this.

The change was performed by running the following (very long) coccinelle patch
on src/:

    @@
    statement S;
    expression E;
    expression F;
    @@

      if (
    (
    dns_hostname_cmp
    |
    eb_memcmp
    |
    memcmp
    |
    strcasecmp
    |
    strcmp
    |
    strncasecmp
    |
    strncmp
    )
    -  (E, F)
    +  (E, F) != 0
      )
    (
      S
    |
      { ... }
    )

    @@
    statement S;
    expression E;
    expression F;
    @@

      if (
    - !
    (
    dns_hostname_cmp
    |
    eb_memcmp
    |
    memcmp
    |
    strcasecmp
    |
    strcmp
    |
    strncasecmp
    |
    strncmp
    )
    -  (E, F)
    +  (E, F) == 0
      )
    (
      S
    |
      { ... }
    )

    @@
    expression E;
    expression F;
    expression G;
    @@

    (
    G &&
    (
    dns_hostname_cmp
    |
    eb_memcmp
    |
    memcmp
    |
    strcasecmp
    |
    strcmp
    |
    strncasecmp
    |
    strncmp
    )
    -  (E, F)
    +  (E, F) != 0
    )

    @@
    expression E;
    expression F;
    expression G;
    @@

    (
    G ||
    (
    dns_hostname_cmp
    |
    eb_memcmp
    |
    memcmp
    |
    strcasecmp
    |
    strcmp
    |
    strncasecmp
    |
    strncmp
    )
    -  (E, F)
    +  (E, F) != 0
    )

    @@
    expression E;
    expression F;
    expression G;
    @@

    (
    (
    dns_hostname_cmp
    |
    eb_memcmp
    |
    memcmp
    |
    strcasecmp
    |
    strcmp
    |
    strncasecmp
    |
    strncmp
    )
    -  (E, F)
    +  (E, F) != 0
    && G
    )

    @@
    expression E;
    expression F;
    expression G;
    @@

    (
    (
    dns_hostname_cmp
    |
    eb_memcmp
    |
    memcmp
    |
    strcasecmp
    |
    strcmp
    |
    strncasecmp
    |
    strncmp
    )
    -  (E, F)
    +  (E, F) != 0
    || G
    )

    @@
    expression E;
    expression F;
    expression G;
    @@

    (
    G &&
    - !
    (
    dns_hostname_cmp
    |
    eb_memcmp
    |
    memcmp
    |
    strcasecmp
    |
    strcmp
    |
    strncasecmp
    |
    strncmp
    )
    -  (E, F)
    +  (E, F) == 0
    )

    @@
    expression E;
    expression F;
    expression G;
    @@

    (
    G ||
    - !
    (
    dns_hostname_cmp
    |
    eb_memcmp
    |
    memcmp
    |
    strcasecmp
    |
    strcmp
    |
    strncasecmp
    |
    strncmp
    )
    -  (E, F)
    +  (E, F) == 0
    )

    @@
    expression E;
    expression F;
    expression G;
    @@

    (
    - !
    (
    dns_hostname_cmp
    |
    eb_memcmp
    |
    memcmp
    |
    strcasecmp
    |
    strcmp
    |
    strncasecmp
    |
    strncmp
    )
    -  (E, F)
    +  (E, F) == 0
    && G
    )

    @@
    expression E;
    expression F;
    expression G;
    @@

    (
    - !
    (
    dns_hostname_cmp
    |
    eb_memcmp
    |
    memcmp
    |
    strcasecmp
    |
    strcmp
    |
    strncasecmp
    |
    strncmp
    )
    -  (E, F)
    +  (E, F) == 0
    || G
    )

    @@
    expression E;
    expression F;
    expression G;
    @@

    (
    - !
    (
    dns_hostname_cmp
    |
    eb_memcmp
    |
    memcmp
    |
    strcasecmp
    |
    strcmp
    |
    strncasecmp
    |
    strncmp
    )
    -  (E, F)
    +  (E, F) == 0
    )
2021-01-04 10:09:02 +01:00
Tim Duesterhus
f89d43a381 MINOR: lua: Use consistent error message 'memory allocation failed'
Other locations in the configuration parser use 'memory allocation failed', so
use this one as well.
2021-01-03 20:37:16 +01:00
Tim Duesterhus
621e74afd1 BUG/MINOR: lua: Fix memory leak error cases in hlua_config_prepend_path
In case of an error `p` is not properly freed.

Minor leak during configuration parsing in out of memory situations, no
backport needed.
2021-01-03 20:37:16 +01:00
Tim Duesterhus
a7ebffef66 BUG/MINOR: sink: Return an allocation failure in __sink_new if strdup() fails
This patch fixes GitHub issue #1023.

The function was introduced in commit 99c453d ("MEDIUM: ring: new
section ring to declare custom ring buffers."), which first appeared
in 2.2-dev9. The fix should be backported to 2.2+.
2021-01-03 20:35:45 +01:00
Thayne McCombs
92149f9a82 MEDIUM: stick-tables: Add srvkey option to stick-table
This allows using the address of the server rather than the name of the
server for keeping track of servers in a backend for stickiness.

The peers code was also extended to support feeding the dictionary using
this key instead of the name.

Fixes #814
2020-12-31 10:04:54 +01:00
Tim Duesterhus
dc38bc4a1a BUG/MEDIUM: cache: Fix hash collision in accept-encoding handling for Vary
This patch fixes GitHub Issue #988. Commit ce9e7b2521
was not sufficient, because it fell back to a hash comparison if the bitmap
of known encodings was not acceptable instead of directly returning the the
cached response is not compatible.

This patch also extends the reg-test to test the hash collision that was
mentioned in #988.

Vary handling is 2.4, no backport needed.
2020-12-31 09:39:08 +01:00
Remi Tricot-Le Breton
e6cc5b5974 MINOR: cache: Replace the "process-vary" option's expected values
Replace the <0/1> expected values of the process-vary option by a more
usual <on/off> pair.
2020-12-24 17:18:00 +01:00
Remi Tricot-Le Breton
42efffd7f6 MINOR: cache: Remove redundant test in http_action_req_cache_use
The suppressed check is fully covered by the next one and can then be
removed.
2020-12-24 17:18:00 +01:00
Remi Tricot-Le Breton
ce9e7b2521 MEDIUM: cache: Manage a subset of encodings in accept-encoding normalizer
The accept-encoding normalizer now explicitely manages a subset of
encodings which will all have their own bit in the encoding bitmap
stored in the cache entry. This way two requests with the same primary
key will be served the same cache entry if they both explicitely accept
the stored response's encoding, even if their respective secondary keys
are not the same and do not match the stored response's one.
The actual hash of the accept-encoding will still be used if the
response's encoding is unmanaged.
The encoding matching and the encoding weight parsing are done for every
subpart of the accept-encoding values, and a bitmap of accepted
encodings is built for every request. It is then tested upon any stored
response that has the same primary key until one with an accepted
encoding is found.
The specific "identity" and "*" accept-encoding values are managed too.
When storing a response in the key, we also parse the content-encoding
header in order to only set the response's corresponding encoding's bit
in its cache_entry encoding bitmap.

This patch fixes GitHub issue #988.
It does not need to be backported.
2020-12-24 17:18:00 +01:00
Remi Tricot-Le Breton
56e46cb393 MINOR: http: Add helper functions to trim spaces and tabs
Add two helper functions that trim leading or trailing spaces and
horizontal tabs from an ist string.
2020-12-24 17:18:00 +01:00
Remi Tricot-Le Breton
6a34b2b65d MINOR: cache: Add specific secondary key comparison mechanism
Add the possibility to define custom comparison functions for every
sub-part of the secondary key hash instead of using a global memcmp.
2020-12-24 17:18:00 +01:00
Remi Tricot-Le Breton
e4421dec7e BUG/MINOR: cache: Manage multiple headers in accept-encoding normalization
The accept-encoding part of the secondary key (vary) was only built out
of the first occurrence of the header. So if a client had two
accept-encoding headers, gzip and br for instance, the key would have
been built out of the gzip string. So another client that only managed
gzip would have been sent the cached resource, even if it was a br resource.
The http_find_header function is now called directly by the normalizers
so that they can manage multiple headers if needed.
A request that has more than 16 encodings will be considered as an
illegitimate request and its response will not be stored.

This fixes GitHub issue #987.

It does not need any backport.
2020-12-24 17:18:00 +01:00
Remi Tricot-Le Breton
2b5c5cbef6 MINOR: cache: Avoid storing responses whose secondary key was not correctly calculated
If any of the secondary hash normalizing functions raises an error, the
secondary hash will be unusable. In this case, the response will not be
stored anymore.
2020-12-24 17:18:00 +01:00
Remi Tricot-Le Breton
bba2912758 MINOR: cache: Refactoring of secondary_key building functions
The two secondary_key building functions (prebuild_full_key
and build_key) have roughly the same content so their code can
be mutualized.
2020-12-24 17:18:00 +01:00
Frdric Lcaille
f63921fc24 MINOR: quic: Add traces for quic_packet_encrypt().
Add traces to have an idea why this function may fail. In fact
in never fails when the passed parameters are correct, especially the
lengths. This is not the case when a packet is not correctly built
before being encrypted.
2020-12-23 11:57:26 +01:00
Frdric Lcaille
133e8a7146 MINOR: quic: make a packet build fails when qc_build_frm() fails.
Even if the size of frames built by qc_build_frm() are computed so that
not to overflow a buffer, do not rely on this and always makes a packet
build fails if we could not build a frame.
Also add traces to have an idea where qc_build_frm() fails.
Fixes a memory leak in qc_build_phdshk_apkt().
2020-12-23 11:57:26 +01:00
Frdric Lcaille
f7e0b8d6ae MINOR: quic: Add traces for in flght ack-eliciting packet counter.
Add trace for this counter. Also shorten its variable name (->ifae_pkts).
2020-12-23 11:57:26 +01:00
Frdric Lcaille
b4e17386cb MINOR: quic: Update the initial salt to that of draft-29.
This salt is ued at leat up to draft-32. At this date ngtcp2 always
uses this salt even if it started the draft-33 development.

Note that when the salt is not correct, we cannot remove the header
protection. In this case the packet number length is wrong.
2020-12-23 11:57:26 +01:00
Frdric Lcaille
47c433fdcb MINOR: quic: Display the SSL alert in ->ssl_send_alert() callback.
At least displays the SSL alert error code passed to ->ssl_send_alert()
QUIC BIO method and the SSL encryption level. This function is newly called
when using picoquic client with a recent version of BoringSSL (Nov 19 2020).
This is not the case with OpenSSL with 32 as QUIC draft implementation.
2020-12-23 11:57:26 +01:00
Frdric Lcaille
26c49d9eb0 MINOR: quic: Add traces to congestion avoidance NewReno callback.
These traces are missing and are useful do diagnose issue in the congestion
avoidance callback for NewReno algorithm.
2020-12-23 11:57:26 +01:00
Frdric Lcaille
0c14020f11 MINOR: quic: Code reordering to help in reviewing/modifying.
Reorder by increasing type the switch/case in qc_parse_pkt_frms()
which is the high level frame parser.
Add new STREAM_X frame types to support some tests with ngtcp2 client.
2020-12-23 11:57:26 +01:00
Frdric Lcaille
f7fe9659f0 MINOR: quic: Flag RX packet as ack-eliciting from the generic parser.
Add ->flags to the QUIC frame parser as this has been done for the builder so
that to flag RX packets as ack-eliciting at low level. This should also be
helpful to maintain the code if we have to add new flags to RX packets.
Remove the statements which does the same thing as higher level in
qc_parse_pkt_frms().
2020-12-23 11:57:26 +01:00
Frdric Lcaille
04ffb66bc9 MINOR: quic: Make usage of the congestion control window.
Remove ->ifcdata which was there to control the CRYPTO data sent to the
peer so that not to saturate its reception buffer. This was a sort
of flow control.
Add ->prep_in_flight counter to the QUIC path struct to control the
number of bytes prepared to be sent so that not to saturare the
congestion control window. This counter is increased each time a
packet was built. This has nothing to see with ->in_flight which
is the real in flight number of bytes which have really been sent.
We are olbiged to maintain two such counters to know how many bytes
of data we can prepared before sending them.
Modify traces consequently which were useful to diagnose issues about
the congestion control window usage.
2020-12-23 11:57:26 +01:00
Frdric Lcaille
c5e72b9868 MINOR: quic: Attempt to make trace more readable
As there is a lot of information in this protocol, this is not
easy to make the traces readable. We remove here a few of them and
shorten some line shortening the variable names.
2020-12-23 11:57:26 +01:00
Frdric Lcaille
8090b51e92 MAJOR: quic: Make usage of ebtrees to store QUIC ACK ranges.
Store QUIC ACK ranges in ebtrees in place of lists with a 0(n) time complexity
for insertion.
2020-12-23 11:57:26 +01:00
Frdric Lcaille
0a76901926 MINOR: cfgparse: QUIC default server transport parameters init.
This patch is there to initialize the default transport parameters for QUIC
as a preparation for one of the QUIC next steps to come: fully support QUIC
protocol for haproxy servers.
2020-12-23 11:57:26 +01:00
Frdric Lcaille
026a7921a5 MINOR: quic: QUIC socket management finalization.
Implement ->accept_conn() callback for QUIC listener sockets.
Note that this patch also implements quic_session_accept() function
which is similar to session_accept_fd() without calling conn_complete_session()
at this time because we do not have any real QUIC mux.
2020-12-23 11:57:26 +01:00
Frdric Lcaille
e9473c7833 MINOR: ssl: QUIC transport parameters parsing.
This patch modifies the TLS ClientHello message callback so that to parse the QUIC
client transport parameters.
2020-12-23 11:57:26 +01:00
Frdric Lcaille
ec216523f7 MINOR: ssl: SSL CTX initialization modifications for QUIC.
Makes TLS/TCP and QUIC share the same CTX initializer so that not to modify the
caller which is an XPRT callback used both by the QUIC xprt and the SSL xprt over
TCP.
2020-12-23 11:57:26 +01:00
Frdric Lcaille
f46c10cfb1 MINOR: server: Add QUIC definitions to servers.
This patch adds QUIC structs to server struct so that to make the QUIC code
compile. Also initializes the ebtree to store the connections by connection
IDs.
2020-12-23 11:57:26 +01:00
Frdric Lcaille
884f2e9f43 MINOR: listener: Add QUIC info to listeners and receivers.
This patch adds a quic_transport_params struct to bind_conf struct
used for the listeners. This is to store the QUIC transport parameters
for the listeners. Also initializes them when calling str2listener().
Before str2sa_range() it's too early to figure we're going to speak QUIC,
and after it's too late as listeners are already created. So it seems that
doing it in str2listener() when the protocol is discovered is the best
place.

Also adds two ebtrees to the underlying receivers to store the connection
by connections IDs (one for the original connection IDs, and another
one for the definitive connection IDs which really identify the connections.

However it doesn't seem normal that it is stored in the receiver nor the
listener. There should be a private context in the listener so that
protocols can store internal information. This element should in
fact be the listener handle.

Something still feels wrong, and probably we'll have to make QUIC and
SSL co-exist: a proof of this is that there's some explicit code in
bind_parse_ssl() to prevent the "ssl" keyword from replacing the xprt.
2020-12-23 11:57:26 +01:00
Frdric Lcaille
a7e7ce957d MINOR: quic: Import C source code files for QUIC protocol.
This patch imports all the C files for QUIC protocol implementation with few
modifications from 20200720-quic branch of quic-dev repository found at
https://github.com/haproxytech/quic-dev.

Traces were implemented to help with the development.
2020-12-23 11:57:26 +01:00
Frdric Lcaille
10caf65634 MINOR: tools: Add support for QUIC addresses parsing.
Add "quic4" and "quic6" keywords to str2sa_range() to parse QUIC IPv4
and IPv6 addresses respectively.
2020-12-23 11:57:26 +01:00
Frdric Lcaille
e50afbd4e4 MINOR: cfgparse: Do not modify the QUIC xprt when parsing "ssl".
When parsing "ssl" keyword for TLS bindings, we must not use the same xprt as the one
for TLS/TCP connections. So, do not modify the QUIC xprt which will be initialized
when parsing QUIC addresses wich "ssl" bindings.
2020-12-23 11:57:26 +01:00
Frdric Lcaille
901ee2f37b MINOR: ssl: Export definitions required by QUIC.
QUIC needs to initialize its BIO and SSL session the same way as for SSL over TCP
connections. It needs also to use the same ClientHello callback.
This patch only exports functions and variables shared between QUIC and SSL/TCP
connections.
2020-12-23 11:57:26 +01:00
Frdric Lcaille
5aa92411fb MINOR: ssl_sock: Initialize BIO and SSL objects outside of ssl_sock_init()
This patch extraces the code which initializes the BIO and SSL session
objects so that to reuse it elsewhere later for QUIC conections which
only needs SSL and BIO objects at th TLS layer stack level to work.
2020-12-23 11:57:26 +01:00
Frdric Lcaille
70da889d57 MINOR: quic: Redefine control layer callbacks which are QUIC specific.
We add src/quic_sock.c QUIC specific socket management functions as callbacks
for the control layer: ->accept_conn, ->default_iocb and ->rx_listening.
accept_conn() will have to be defined. The default I/O handler only recvfrom()
the datagrams received. Furthermore, ->rx_listening callback always returns 1 at
this time but should returns 0 when reloading the processus.
2020-12-23 11:57:26 +01:00
Frdric Lcaille
ca42b2c9d3 MINOR: protocol: Create proto_quic QUIC protocol layer.
As QUIC is a connection oriented protocol, this file is almost a copy of
proto_tcp without TCP specific features. To suspend/resume a QUIC receiver
we proceed the same way as for proto_udp receivers.

With the recent updates to the listeners, we don't need a specific set of
quic*_add_listener() functions, the default ones are sufficient. The fields
declaration were reordered to make the various layers more visible like in
other protocols.

udp_suspend_receiver/udp_resume_receiver are up-to-date (the check for INHERITED
is present) and the code being UDP-specific, it's normal to use UDP here.
Note that in the future we might more reasily reference stacked layers so that
there's no more need for specifying the pointer here.
2020-12-23 11:57:26 +01:00
Dragan Dosen
04bf0cc086 MINOR: sample: add the xxh3 converter
This patch adds support for the XXH3 variant of hash function that
generates a 64-bit hash.
2020-12-23 06:39:21 +01:00
Dragan Dosen
6bfe425679 CLEANUP: xxhash: remove the unused src/xxhash.c
The source file src/xxhash.c is removed, as we use XXH_INLINE_ALL.
2020-12-23 06:39:21 +01:00
Dragan Dosen
967e7e79af MEDIUM: xxhash: use the XXH3 functions to generate 64-bit hashes
Replace the XXH64() function calls with the XXH3 variant function
XXH3_64bits_withSeed() where possible.
2020-12-23 06:39:21 +01:00
Dragan Dosen
de37443e64 IMPORT: xxhash: update to v0.8.0 that introduces stable XXH3 variant
A new XXH3 variant of hash functions shows a noticeable improvement in
performance (especially on small data), and also brings 128-bit support,
better inlining and streaming capabilities.

Performance comparison is available here:

  https://github.com/Cyan4973/xxHash/wiki/Performance-comparison
2020-12-23 06:39:21 +01:00
Amaury Denoyelle
6d975f0af6 MINOR: check: do not ignore a connection header for http-check send
Allow the user to specify a custom Connection header for http-check
send. This is useful for example to implement a websocket upgrade check.

If no connection header has been set, a 'Connection: close' header is
automatically appended to allow the server to close the connection
immediately after the request/response.

Update the documentation related to http-check send.

This fixes the github issue #1009.
2020-12-22 14:22:44 +01:00
Tim Duesterhus
12a08d8849 BUG/MEDIUM: mux_h2: Add missing braces in h2_snd_buf()around trace+wakeup
This is a regression in 7838a79ba ("MEDIUM: mux-h2/trace: add lots of traces
all over the code"). The issue was found using -Wmisleading-indentation.
This patch fixes GitHub issue #1015.

The impact of this bug is that it could in theory cause occasional delays
on some long responses for connections having otherwise no traffic.

This patch should be backported to 2.1+, the commit was first tagged in
v2.1-dev2.
2020-12-22 09:02:11 +01:00
Ilya Shipitsin
f38a01884a CLEANUP: assorted typo fixes in the code and comments
This is 13n iteration of typo fixes
2020-12-21 11:24:48 +01:00
Baptiste Assmann
949a7f6459 BUG/MINOR: dns: SRV records ignores duplicated AR records
This bug happens when a service has multiple records on the same host
and the server provides the A/AAAA resolution in the response as AR
(Additional Records).

In such condition, the first occurence of the host will be taken from
the Additional section, while the second (and next ones) will be process
by an independent resolution task (like we used to do before 2.2).
This can lead to a situation where the "synchronisation" of the
resolution may diverge, like described in github issue #971.

Because of this behavior, HAProxy mixes various type of requests to
resolve the full list of servers: SRV+AR for all "first" occurences and
A/AAAA for all other occurences of an existing hostname.
IE: with the following type of response:

   ;; ANSWER SECTION:
   _http._tcp.be2.tld.     3600    IN      SRV     5 500 80 A2.tld.
   _http._tcp.be2.tld.     3600    IN      SRV     5 500 86 A3.tld.
   _http._tcp.be2.tld.     3600    IN      SRV     5 500 80 A1.tld.
   _http._tcp.be2.tld.     3600    IN      SRV     5 500 85 A3.tld.

   ;; ADDITIONAL SECTION:
   A2.tld.                 3600    IN      A       192.168.0.2
   A3.tld.                 3600    IN      A       192.168.0.3
   A1.tld.                 3600    IN      A       192.168.0.1
   A3.tld.                 3600    IN      A       192.168.0.3

the first A3 host is resolved using the Additional Section and the
second one through a dedicated A request.

When linking the SRV records to their respective Additional one, a
condition was missing (chek if said SRV record is already attached to an
Additional one), leading to stop processing SRV only when the target
SRV field matches the Additional record name. Hence only the first
occurence of a target was managed by an additional record.
This patch adds a condition in this loop to ensure the record being
parsed is not already linked to an Additional Record. If so, we can
carry on the parsing to find a possible next one with the same target
field value.

backport status: 2.2 and above
2020-12-21 11:19:09 +01:00
Ilya Shipitsin
af204881a3 BUILD: ssl: fine guard for SSL_CTX_get0_privatekey call
SSL_CTX_get0_privatekey is openssl/boringssl specific function present
since openssl-1.0.2, let us define readable guard for it, not depending
on HA_OPENSSL_VERSION
2020-12-21 11:17:36 +01:00
Willy Tarreau
c7ead07b9c CLEANUP: debug: mark the RNG's seed as unsigned
Since commit 8a069eb9a ("MINOR: debug: add a trivial PRNG for scheduler
stress-tests"), 32-bit gcc 4.7 emits this warning when parsing the
initial seed for the debugger's RNG (2463534242):

  src/debug.c:46:1: warning: this decimal constant is unsigned only in ISO C90 [enabled by default]

Let's mark it explicitly unsigned.
2020-12-18 16:31:08 +01:00
Christopher Faulet
0c366a8761 BUG/MEDIUM: mux-h1: Handle h1_process() failures on a pipelined request
On frontend side, when a conn-stream is detached from a H1 connection, the
H1 stream is destroyed and if we already have some data to parse (a
pipelined request), we process these data immedialtely calling
h1_process(). Then we adjust the H1 connection timeout. But h1_process() may
fail and release the H1 connection. For instance, a parsing error may be
reported. Thus, when that happens, we must not use anymore the H1 connection
and exit.

This patch must be backported as far as the 2.2. This bug can impact the 2.3
and the 2.2, in theory, if h1 stream creation fails. But, concretly, it only
fails on the 2.4 because the requests are now parsed at this step.
2020-12-18 15:13:58 +01:00
Christopher Faulet
fac0f8f029 CLEANUP: mux-h2: Rename h2c_frt_handle_data() to be generic
h2c_frt_handle_data() is now used to parse DATA frames on the frontend and
the backend side. Thus it is renamed into h2c_handle_data().
2020-12-18 15:05:57 +01:00
Christopher Faulet
142854b1da CLEANUP: mux-h2: Rename h2s_frt_make_resp_data() to be generic
h2s_frt_make_resp_data() is now used to emit DATA frames on the frontend and
the backend side. Thus it is renamed into h2s_make_data().
2020-12-18 15:05:57 +01:00
Christopher Faulet
198ef8b1de BUG/MEDIUM: http-ana: Never for sending data in TUNNEL mode
When a channel is set in TUNNEL mode, we now always set the CF_NEVER_WAIT flag,
to be sure to never wait for sending data. It is important because in TUNNEL
mode, we have no idea if more data are expected or not. Setting this flag
prevent the MSG_MORE flag to be set on the connection.

It is only a problem with the HTX, since the 2.2. On previous versions, the
MSG_MORE flag is only set on the mux initiative. In fact, the problem arises
because there is an ambiguity in tunnel mode about the HTX_FL_EOI flag. In this
mode, from the mux point of view, while the SHUTR is not received more data are
expected. But from the channel point of view, we want to send data asap.

At short term, this fix is good enough and is valid anyway. But for the long
term more reliable solution must be found. At least, the to_forward field must
regain its original meaning.

This patch must be backported as far as 2.2.
2020-12-18 15:05:57 +01:00
Christopher Faulet
3e1748bbf3 BUG/MINOR: mux-h1: Don't set CS_FL_EOI too early for protocol upgrade requests
When a protocol upgrade request is received, once parsed, it is waiting for
the response in the DONE state. But we must not set the flag CS_FL_EOI
because we don't know if a protocol upgrade will be performed or not.

Now, it is set on the response path, if both sides reached the DONE
state. If a protocol upgrade is finally performed, both side are switched in
TUNNEL state. Thus the CS_FL_EOI flag is not set.

If backported, this patch must be adapted because for now it relies on last
2.4-dev changes. It may be backported as far as 2.0.
2020-12-18 15:05:57 +01:00
Christopher Faulet
c75668ebff BUG/MINOR: http: Establish a tunnel for all 2xx responses to a CONNECT
As stated in the rfc7231, section 4.3.6, an HTTP tunnel via a CONNECT method
is successfully established if the server replies with any 2xx status
code. However, only 200 responses are considered as valid. With this patch,
any 2xx responses are now considered to estalish the tunnel.

This patch may be backported on demand to all stable versions and adapted
for the legacy HTTP. It works this way since a very long time and nobody
complains.
2020-12-18 15:05:57 +01:00
Miroslav Zagorac
7f8314c8d1 MINOR: opentracing: add ARGC_OT enum
Due to the addition of the OpenTracing filter it is necessary to define
ARGC_OT enum.  This value is used in the functions fmt_directive() and
smp_resolve_args().
2020-12-16 15:49:53 +01:00
Miroslav Zagorac
6deab79d59 MINOR: vars: replace static functions with global ones
The OpenTracing filter uses several internal HAProxy functions to work
with variables and therefore requires two static local HAProxy functions,
var_accounting_diff() and var_clear(), to be declared global.

In fact, the var_clear() function was not originally defined as static,
but it lacked a declaration.
2020-12-16 14:20:08 +01:00
Remi Tricot-Le Breton
5853c0c0d5 MINOR: cache: Add a max-secondary-entries cache option
This new option allows to tune the maximum number of simultaneous
entries with the same primary key in the cache (secondary entries).
When we try to store a response in the cache and there are already
max-secondary-entries living entries in the cache, the storage will
fail (but the response will still be sent to the client).
It defaults to 10 and does not have a maximum number.
2020-12-15 16:35:09 +01:00
Remi Tricot-Le Breton
73be796462 MEDIUM: cache: Avoid going over duplicates lists too often
The secondary entry counter cannot be updated without going over all the
items of a duplicates list periodically. In order to avoid doing it too
often and to impact the cache's performances, a timestamp is added to
the cache_entry. It will store the timestamp (with second precision) of
the last iteration over the list (actually the last call of the
clear_expired_duplicates function). This way, this function will not be
called more than once per second for a given duplicates list.
2020-12-15 16:35:09 +01:00
Remi Tricot-Le Breton
65904e4f07 MEDIUM: cache: Add a secondary entry counter and insertion limitation
Add an arbitrary maximum number of secondary entries per primary hash
(10 for now) to the cache. This prevents the cache from being filled
with duplicates of the same resource.
This works thanks to an entry counter that is kept in one of the
duplicates of the list (the last one).
When an entry is added to the list, the ebtree's implementation ensures
that it will be added to the end of the existing list so the only thing
to do to keep the counter updated is to get the previous counter from
the second to last entry.
Likewise, when an entry is explicitely deleted, we update the counter
from the list's last item.
2020-12-15 16:35:09 +01:00
Ilya Shipitsin
ec60909871 BUILD: SSL: fine guard for SSL_CTX_add_server_custom_ext call
SSL_CTX_add_server_custom_ext is openssl specific function present
since openssl-1.0.2, let us define readable guard for it, not depending
on HA_OPENSSL_VERSION
2020-12-15 16:13:35 +01:00
Remi Tricot-Le Breton
964caaff0e BUG/MAJOR: cache: Crash because of disabled entry not removed from the tree
The cache entries are now added into the tree even when they are not
complete yet. If we realized while trying to add a response's payload
that the shctx was full, the entry was disabled through the
disable_cache_entry function, which cleared the key field of the entry's
node, but without actually removing it from the tree. So the shctx row
could be stolen from the entry and the row's content be rewritten while
a lookup in the tree would still find a reference to the old entry. This
caused a random crash in case of cache saturation and row reuse.
This patch adds the missing removal of the node from the tree next to
the reset of the key in disable_cache_entry.

This bug was introduced by commit 3243447 ("MINOR: cache: Add entry
to the tree as soon as possible")

It does not need to be backported.
2020-12-15 15:31:30 +01:00
William Lallemand
a55685bfea BUG/MEDIUM: ssl/crt-list: bad behavior with "commit ssl cert"
In issue #1004, it was reported that it is not possible to remove
correctly a certificate after updating it when it came from a crt-list.

Indeed the "commit ssl cert" command on the CLI does not update the list
of ckch_inst in the crtlist_entry. Because of this, the "del ssl
crt-list" command does not remove neither the instances nor the SNIs
because they were never linked to the crtlist_entry.

This patch fixes the issue by inserting the ckch_inst in the
crtlist_entry once generated.

Must be backported as far as 2.2.
2020-12-15 15:13:21 +01:00
Christopher Faulet
cc043f66b7 BUG/MEDIUM: mux-h1: Fix a deadlock when a 408 error is pending for a client
When a frontend H1 connection timed out waiting for the next request, a 408
error message is returned to the client. It is performed into the H1C task
process function, h1_timeout_task(), and under the idle connection takeover
lock. If the 408 error message cannot be sent immediately, we wait for a
next retry. In this case, the lock must be released.

This bug was introduced by the commit c4bfa59f1d ("MAJOR: mux-h1: Create the
client stream as later as possible") and is specific to the 2.4-DEV. No
backport needed.
2020-12-14 10:06:13 +01:00
Christopher Faulet
cb33d3ac7f BUG/MEDIUM: lb-leastconn: Reposition a server using the right eweight
Depending on the context, the current eweight or the next one must be used
to reposition a server in the tree. When the server state is updated, for
instance its weight, the next eweight must be used because it is not yet
committed. However, when the server is used, on normal conditions, the
current eweight must be used.

In fact, it is only a bug on the 1.8. On newer versions, the changes on a
server are performed synchronously. But it is safer to rely on the right
eweight value to avoid any futur bugs.

On the 1.8, it is important to do so, because the server state is updated
and committed inside the rendez-vous point. Thus, the next server state may
be unsync with the current state for a short time, waiting all threads join
the rendez-vous point. It is especially a problem if the next eweight is set
to 0. Because otherwise, it must not be used to reposition the server in the
tree, leading to a divide by 0.

This patch must be backported as far as 1.8.
2020-12-14 09:52:34 +01:00
Willy Tarreau
746b0515a4 MEDIUM: connection: make use of the control layer check_events/ignore_events
This changes the subscribe/unsubscribe functions to rely on the control
layer's check_events/ignore_events. At the moment only the socket version
of these functions is present so the code should basically be the same.
2020-12-11 17:06:11 +01:00
Willy Tarreau
472125bc04 MINOR: protocol: add a pair of check_events/ignore_events functions at the ctrl layer
Right now the connection subscribe/unsubscribe code needs to manipulate
FDs, which is not compatible with QUIC. In practice what we need there
is to be able to either subscribe or wake up depending on readiness at
the moment of subscription.

This commit introduces two new functions at the control layer, which are
provided by the socket code, to check for FD readiness or subscribe to it
at the control layer. For now it's not used.
2020-12-11 17:02:50 +01:00
Willy Tarreau
2ded48dd27 MINOR: connection: make conn_sock_drain() use the control layer's ->drain()
Now we don't touch the fd anymore there, instead we rely on the ->drain()
provided by the control layer. As such the function was renamed to
conn_ctrl_drain().
2020-12-11 16:26:01 +01:00
Willy Tarreau
427c846cc9 MINOR: protocol: add a ->drain() function at the connection control layer
This is what we need to drain pending incoming data from an connection.
The code was taken from conn_sock_drain() without the connection-specific
stuff. It still takes a connection for now for API simplicity.
2020-12-11 16:26:00 +01:00
Willy Tarreau
586f71b43f REORG: connection: move the socket iocb (conn_fd_handler) to sock.c
conn_fd_handler() is 100% specific to socket code. It's about time
it moves to sock.c which manipulates socket FDs. With it comes
conn_fd_check() which tests for the socket's readiness. The ugly
connection status check at the end of the iocb was moved to an inlined
function in connection.h so that if we need it for other socket layers
it's not too hard to reuse.

The code was really only moved and not changed at all.
2020-12-11 16:26:00 +01:00
Willy Tarreau
827fee7406 MINOR: connection: remove sock-specific code from conn_sock_send()
The send() loop present in this function and the error handling is already
present in raw_sock_from_buf(). Let's rely on it instead and stop touching
the FD from this place. The send flag was changed to use a more agnostic
CO_SFL_*. The name was changed to "conn_ctrl_send()" to remind that it's
meant to be used to send at the lowest level.
2020-12-11 16:25:11 +01:00
Amaury Denoyelle
f7719a25db MINOR: stream: add timeout sample fetches
Add cur_server_timeout and cur_tunnel_timeout.

These sample fetches return the current timeout value for a stream. This
is useful to retrieve the value of a timeout which was changed via a
set-timeout rule.
2020-12-11 12:01:07 +01:00
Amaury Denoyelle
12bada5662 MINOR: stream: add sample fetches
Prepare the possibility to register sample fetches on the stream.

This commit is necessary to implement sample fetches to retrieve the
current timeout values.
2020-12-11 12:01:07 +01:00
Amaury Denoyelle
d91d779618 MINOR: backend: add timeout sample fetches
Add be_server_timeout and be_tunnel_timeout.

These sample fetches return the configuration value for server or tunnel
timeout on the backend side.
2020-12-11 12:01:07 +01:00
Amaury Denoyelle
da184d5306 MINOR: frontend: add client timeout sample fetch
Add a sample fetch named fe_client_timeout to return the configuration
value for the client timeout on a frontend.
2020-12-11 12:01:07 +01:00
Amaury Denoyelle
8d22823ade MEDIUM: http_act: define set-timeout server/tunnel action
Add a new http-request action 'set-timeout [server/tunnel]'. This action
can be used to update the server or tunnel timeout of a stream. It takes
two parameters, the timeout name to update and the new timeout value.
This rule is only valid for a proxy with backend capabilities. The
timeout value cannot be null. A sample expression can also be used
instead of a plain value.
2020-12-11 12:01:07 +01:00
Amaury Denoyelle
fb50443517 MEDIUM: stream: support a dynamic tunnel timeout
Allow the modification of the tunnel timeout on the stream side.
Use a new field in the stream for the tunnel timeout. It is initialized
by the tunnel timeout from backend unless it has already been set by a
set-timeout tunnel rule.
2020-12-11 12:01:07 +01:00
Amaury Denoyelle
90d3d882e3 MEDIUM: stream: support a dynamic server timeout
Allow the modification of the timeout server value on the stream side.
Do not apply the default backend server timeout in back_establish if it
is already defined. This is the case if a set-timeout server rule has
been executed.
2020-12-11 12:01:07 +01:00
Amaury Denoyelle
b715078821 MINOR: stream: prepare the hot refresh of timeouts
Define a stream function to allow to update the timeouts.
This commit is in preparation for the support of dynamic timeouts with
the set-timeout rule.
2020-12-11 12:01:07 +01:00
Christopher Faulet
82635a0fc1 BUG/MINOR: tools: Reject size format not starting by a digit
parse_size_err() function is now more strict on the size format. The first
character must be a digit. Otherwise an error is returned. Thus "size k" is
now rejected.

This patch must be backported to all stable versions.
2020-12-11 12:01:07 +01:00
Christopher Faulet
c20ad0d8db BUG/MINOR: tools: make parse_time_err() more strict on the timer validity
First, an error is now reported if the first character is not a digit. Thus,
"timeout client s" triggers an error now. Then 'u' is also rejected
now. 'us' is valid and should be used set the timer in microseconds. However
'u' alone is not a valid unit. It was just ignored before (default to
milliseconds). Now, it is an error. Finally, a warning is reported if the
end of the text is not reached after the timer parsing. This warning will
probably be switched to an error in a futur version.

This patch must be backported to all stable versions.
2020-12-11 12:01:04 +01:00
Christopher Faulet
cad5f5e1ed MINOR: tcpcheck: Only wait for more payload data on HTTP expect rules
For HTTP expect rules, if the buffer is not empty, it is guarantee that all
responses headers are received, with the start-line. Thus, except for
payload matching, there is no reason to wait for more data from the moment
the htx message is not empty.

This patch may be backported as far as 2.2.
2020-12-11 11:48:15 +01:00
Christopher Faulet
c878f56f7c BUG/MINOR: tcpcheck: Don't rearm the check timeout on each read
The check timeout is used to limit a health-check execution. By default
inter timeout is used. But when defined the check timeout is used. In this
case, the inter timeout (or connect timeout) is used for the connection
establishment only. And the check timeout for the health-check
execution. Thus, it must be set after a successfull connect. It means it is
rearm at the end of each connect rule.

This patch with the previous one (BUG/MINOR: http-check: Use right condition
to consider HTX message as full) should solve the issue #991. It must be
backported as far as 2.2. On the 2.3 and 2.2, there are 2 places were the
connection establishement is handled. The check timeout must be set on both.
2020-12-11 11:48:15 +01:00
Christopher Faulet
3f527197cd BUG/MINOR: http-check: Use right condition to consider HTX message as full
When an HTTP expect rule is evaluated, we must know if more data is expected
or not to wait if the matching fails. If the whole response is received or
if the HTX message is full, we must not wait. In this context,
htx_free_data_space() must be used instead of htx_free_space(). The fisrt
one count down the block size. Otherwise at the edge, when only the block
size remains free (8 bytes), we may think there is some place for more data
while the mux is unable to add more block.

This bug explains the loop described on the GH issue #991. It should be
backported as far as 2.2.
2020-12-11 11:48:15 +01:00
Willy Tarreau
8b250ba738 CLEANUP: connection: open-code conn_cond_update_polling() and update the comment
This last call to conn_cond_update_polling() is now totally misleading as
the function only stops polling in case of unrecoverable connection error.
Let's open-code the test to make it more prominent and explain what we're
trying to do there. It's even almost certain this code is never executed
anymore, as the only remaining case should be a mux's wake function setting
CO_FL_ERROR without disabling the polling, but they need to be audited first
to make sure this is the case.
2020-12-11 11:19:24 +01:00
Willy Tarreau
f7e4a6fc07 MINOR: checks: don't call conn_cond_update_polling() anymore
This was a leftover of the pre-mux v1.8-dev3 era. It makes no sense anymore
to try to disable polling on a connection we don't own, it's the mux's job
and it's properly done upon shutdowns and closes.
2020-12-11 11:11:06 +01:00
Willy Tarreau
30bd4efb1b MINOR: checks: use cs_drain_and_close() instead of draining the connection
As explained in previous commit, the situation is absurd as we try to
cleanly drain pending data before impolitely shutting down, and it could
be counter productive on real muxes. Let's use cs_drain_and_close() instead.
2020-12-11 11:09:29 +01:00
Willy Tarreau
7d7b11cf93 MINOR: mux-pt: take care of CS_SHR_DRAIN in shutr()
When the shutr() requests CS_SHR_DRAIN and there's no particular shutr
implemented on the underlying transport layer, we must drain pending data.
This is what happens when cs_drain_and_close() is called. It is important
for TCP checks to drain large responses and close cleanly.
2020-12-11 11:07:19 +01:00
Willy Tarreau
a5ea751922 MINOR: stream-int: don't touch polling anymore on shutdown
Not only it's become totally useless with muxes, in addition it's
dangerous to play with the mux's FD while shutting a stream down for
writes. It's already done *if necessary* by the cs_shutw() code at the
mux layer. Fortunately it doesn't seem to have any impact, most likely
the polling updates used to immediately revert this operation.
2020-12-11 10:29:11 +01:00
Willy Tarreau
5a1d439225 CLEANUP: connection: use fd_stop_both() instead of conn_stop_polling()
conn_stop_polling() in fact only calls fd_stop_both() after checking
that the ctrl layer is ready. It's the case in conn_fd_check() so
let's get rid of this next-to-last user of this function.
2020-12-11 09:56:53 +01:00
Remi Tricot-Le Breton
e3e1e5f34b MINOR: cache: Dump secondary entries in "show cache"
The duplicated entries (in case of vary) were not taken into account by
the "show cache" command. They are now dumped too.
A new "vary" column is added to the output. It contains the complete
seocndary key (in hex format).
2020-12-10 15:59:49 +01:00
Willy Tarreau
29885f0308 MINOR: udp: export udp_suspend_receiver() and udp_resume_receiver()
QUIC will rely on UDP at the receiver level, and will need these functions
to suspend/resume the receivers. In the future, protocol chaining may
simplify this.
2020-12-08 18:10:18 +01:00
Willy Tarreau
de471c4655 MINOR: protocol: add a set of ctrl_init/ctrl_close methods for setup/teardown
Currnetly conn_ctrl_init() does an fd_insert() and conn_ctrl_close() does an
fd_delete(). These are the two only short-term obstacles against using a
non-fd handle to set up a connection. Let's have pur these into the protocol
layer, along with the other connection-level stuff so that the generic
connection code uses them instead. This will allow to define new ones for
other protocols (e.g. QUIC).

Since we only support regular sockets at the moment, the code was placed
into sock.c and shared with proto_tcp, proto_uxst and proto_sockpair.
2020-12-08 15:50:56 +01:00
Willy Tarreau
b366c9a59a CLEANUP: protocol: group protocol struct members by usage
For the sake of an improved readability, let's group the protocol
field members according to where they're supposed to be defined:
  - connection layer (note: for now even UDP needs one)
  - binding layer
  - address family
  - socket layer
Nothing else was changed.
2020-12-08 14:58:24 +01:00
Willy Tarreau
b9b2fd7cf4 MINOR: protocol: export protocol definitions
The various protocols were made static since there was no point in
exporting them in the past. Nowadays with QUIC relying on UDP we'll
significantly benefit from UDP being exported and more generally from
being able to declare some functions as being the same as other
protocols'.

In an ideal world it should not be these protocols which should be
exported, but the intermediary levels:
  - socket layer (sock.c only right now), already exported as functions
    but nothing structured at the moment ;
  - family layer (sock_inet, sock_unix, sockpair etc): already structured
    and exported
  - binding layer (the part that relies on the receiver): currently fused
    within the protocol
  - connectiong layer (the part that manipulates connections): currently
    fused within the protocol
  - protocol (connection's control): shouldn't need to be exposed
    ultimately once the elements above are in an easily sharable way.
2020-12-08 14:54:08 +01:00
Willy Tarreau
f9ad06cb26 MINOR: protocol: remove the redundant ->sock_domain field
This field used to be needed before commit 2b5e0d8b6 ("MEDIUM: proto_udp:
replace last AF_CUST_UDP* with AF_INET*") as it was used as a protocol
entry selector. Since this commit it's always equal to the socket family's
value so it's entirely redundant. Let's remove it now to simplify the
protocol definition a little bit.
2020-12-08 12:13:54 +01:00
Christopher Faulet
c43fca0139 BUG/MINOR: stream: Don't use input buffer after the ownership xfer
At the end of stream_new(), once the input buffer is transfer to the request
channel, it must not be used anymore. The previous patch (16df178b6 "BUG/MEDIUM:
stream: Xfer the input buffer to a fully created stream") was pushed to quickly.

No backport needed.
2020-12-04 17:22:50 +01:00
Christopher Faulet
16df178b6e BUG/MEDIUM: stream: Xfer the input buffer to a fully created stream
The input buffer passed as argument to create a new stream must not be
transferred when the request channel is initialized because the channel
flags are not set at this stage. In addition, the API is a bit confusing
regarding the buffer owner when an error occurred. The caller remains the
owner, but reading the code it is not obvious.

So, first of all, to avoid any ambiguities, comments are added on the
calling chain to make it clear. The buffer owner is the caller if any error
occurred. And the ownership is transferred to the stream on success.

Then, to make things simple, the ownership is transferred at the end of
stream_new(), in case of success. And the input buffer is updated to point
on BUF_NULL. Thus, in all cases, if the caller try to release it calling
b_free() on it, it is not a problem. Of course, it remains the caller
responsibility to release it on error.

The patch fixes a bug introduced by the commit 26256f86e ("MINOR: stream:
Pass an optional input buffer when a stream is created"). No backport is
needed.
2020-12-04 17:15:03 +01:00
William Lallemand
b7fdfdfd92 MEDIUM: ssl: fatal error with bundle + openssl < 1.1.1
Since HAProxy 2.3, OpenSSL 1.1.1 is a requirement for using a
multi-certificate bundle in the configuration. This patch emits a fatal
error when HAProxy tries to load a bundle with an older version of
HAProxy.

This problem was encountered by an user in issue #990.

This must be backported in 2.3.
2020-12-04 15:45:02 +01:00
Willy Tarreau
d1f250f87b MINOR: listener: now use a generic add_listener() function
With the removal of the family-specific port setting, all protocol had
exactly the same implementation of ->add(). A generic one was created
with the name "default_add_listener" so that all other ones can now be
removed. The API was slightly adjusted so that the protocol and the
listener are passed instead of the listener and the port.

Note that all protocols continue to provide this ->add() method instead
of routinely calling default_add_listener() from create_listeners(). This
makes sure that any non-standard protocol will still be able to intercept
the listener addition if needed.

This could be backported to 2.3 along with the few previous patches on
listners as a pure code cleanup.
2020-12-04 15:08:00 +01:00
Willy Tarreau
07400c56bb MINOR: listener: automatically set the port when creating listeners
In create_listeners() we iterate over a port range and call the
protocol's ->add() function to add a new listener on the specified
port. Only tcp4/tcp6/udp4/udp6 support a port, the other ones ignore
it. Now that we can rely on the address family to properly set the
port, better do it this way directly from create_listeners() and
remove the family-specific case from the protocol layer.
2020-12-04 15:08:00 +01:00
Willy Tarreau
73bed9ff13 MINOR: protocol: add a ->set_port() helper to address families
At various places we need to set a port on an IPv4 or IPv6 address, and
it requires casts that are easy to get wrong. Let's add a new set_port()
helper to the address family to assist in this. It will be directly
accessible from the protocol and will make the operation seamless.
Right now this is only implemented for sock_inet as other families do
not need a port.
2020-12-04 15:08:00 +01:00
Christopher Faulet
c31bc724d4 MINOR: h1-htx/http-ana: Set BODYLESS flag on message in TUNNEL state
When a H1 message is parsed, if the parser state is switched to TUNNEL mode
just after the header parsing, the BODYLESS flag is set on the HTX
start-line. By transitivity, the corresponding flag is set on the message in
HTTP analysers.  Thus it is possible to rely on it to not wait for the
request body.
2020-12-04 14:41:49 +01:00
Christopher Faulet
2a40854244 MINOR: http-ana: Properly set message flags from the start-line flags
CNT_LEN and TE_CHNK flags must be set on the message only when the
corresponding flag is set on the HTX start-line. Before, when the transfer
length was known XFER_LEN set), the HTTP_MSGF_TE_CHNK was the default. But
it is not appropriate. Now, it is only set if the message is chunked. Thus,
it is now possible to have a known transfer length without CNT_LEN or
TE_CHNK.

In addition, the BODYLESS flags may be set, independently on XFER_LEN one.
2020-12-04 14:41:49 +01:00
Christopher Faulet
6ad06066cd CLEANUP: connection: Remove CS_FL_READ_PARTIAL flag
Since the recent refactoring of the H1 multiplexer, this flag is no more
used. Thus it is removed.
2020-12-04 14:41:49 +01:00
Christopher Faulet
da831fa068 CLEANUP: http-ana: Remove TX_WAIT_NEXT_RQ unsued flag
This flags is now unused. It was used in REQ_WAIT_HTTP analyser, when a
stream was waiting for a request, to set the keep-alive timeout or to avoid
to send HTTP errors to client.
2020-12-04 14:41:49 +01:00
Christopher Faulet
8bebd2fe52 MEDIUM: http-ana: Don't process partial or empty request anymore
It is now impossible to start the HTTP request processing in the stream
analysers with a partial or empty request message. The mux-h2 was already
waiting of the request headers before creating the stream. Now the mux-h1
does the same. All errors (aborts, timeout or invalid requests) waiting for
the request headers are now handled by the multiplexers. So there is no
reason to still handle them in the REQ_WAIT_HTTP (http_wait_for_request)
analyser.

To ensure there is no ambiguity, a BUG_ON() was added to exit if a partial
request is received in this analyser.
2020-12-04 14:41:49 +01:00
Christopher Faulet
2afd874704 CLEANUP: htx: Remove HTX_FL_UPGRADE unsued flag
Now the H1 to H2 upgrade is handled before the stream
creation. HTX_FL_UPGRADE flag is now unused.
2020-12-04 14:41:49 +01:00
Christopher Faulet
4a8779f808 MINOR: http-ana: Remove useless update of t_idle duration of the stream
Becaues the stream is now created after the request headers parsing, the
idle duration from the session is always up-to-date.
2020-12-04 14:41:49 +01:00
Christopher Faulet
3ced1d1db4 CLEANUP: mux-h1: Rename H1C_F_CS_* flags and reorder H1C flags
H1C_F_CS_* flags are renamed into H1C_F_ST_*. They reflect the connection
state. So "ST" is well suited. "CS" is confusing because it is also the
abbreviation for conn-stream.

In addition, H1C flags are reordered.
2020-12-04 14:41:49 +01:00
Christopher Faulet
c4bfa59f1d MAJOR: mux-h1: Create the client stream as later as possible
This is the reason for all previous patches. The conn-stream and the
associated stream are created as later as possible. It only concerns the
frontend connections. But it means the request headers, and possibly the
first data block, are received and parsed before the conn-stream
creation. To do so, an embryonic H1 stream, with no conn-stream, is
created. The result of this "early parsing" is stored in its rx buffer, used
to fill the request channel when the stream is created. During this step,
some HTTP errors may be returned by the mux. It must also handle
http-request/keep-alive timeouts. A significative change is about H1 to H2
upgrade. It happens very early now, and no H1 stream are created (and thus
of course no conn-stream).

The most important part of this patch is located to the h1_process()
function. Because it must trigger the parsing when there is no H1
stream. h1_recv() function has also been simplified.
2020-12-04 14:41:49 +01:00
Christopher Faulet
c18fc234d9 MINOR: mux-h1: Add functions to send HTTP errors from the mux
For now, this part is unsued. But this patch adds functions to handle errors
on idle and embryonic H1 connections and send corresponding HTTP error
messages to the client (400, 408 or 500). Thanks to previous patches, these
functions take care to update the right stats counters, but also the
counters tracked by the session.

A field to store the HTTP error code has been added in the H1C structure. It
is used for error retransmits, if any, and to get it in http logs. It is
used to return the mux exit status code when the MUX_EXIT_STATUS ctl
parameter is requested.
2020-12-04 14:41:49 +01:00
Christopher Faulet
ce5e6bcb04 MINOR: logs: Get the multiplexer exist status when no stream is provided
When a log message is emitted from the session level, by a multiplexer,
there is no stream. Thus for HTTP session, there no status code and the
termination flags are not correctly set.

Thanks to previous patch, the HTTP status code is deduced from the mux exist
status, using the MUX_EXIT_STATE ctl param. This is only done for HTTP
frontends. If it is defined ( != 0), it is used to deduce the termination
flags.
2020-12-04 14:41:49 +01:00
Christopher Faulet
4c8ad84232 MINOR: mux: Add a ctl parameter to get the exit status of the multiplexers
The ctl param MUX_EXIT_STATUS can be request to get the exit status of a
multiplexer. For instance, it may be an HTTP status code or an H2 error. For
now, 0 is always returned. When the mux h1 will be able to return HTTP
errors itself, this ctl param will be used to get the HTTP status code from
the logs.

the mux_exit_status enum has been created to map internal mux exist status
to generic one. Thus there is 5 possible status for now: success, invalid
error, timeout error, internal error and unknown.
2020-12-04 14:41:49 +01:00
Christopher Faulet
84600631cd MINOR: stick-tables: Add functions to update some values of a tracked counter
The cumulative numbers of http requests, http errors, bytes received and
sent and their respective rates for a tracked counters are now updated using
specific stream independent functions. These functions are used by the
stream but the aim is to allow the session to do so too. For now, there is
no reason to perform these updates from the session, except from the mux-h2
maybe. But, the mux-h1, on the frontend side, will be able to return some
errors to the client, before the stream creation. In this case, it will be
mandatory to update counters tracked at the session level.
2020-12-04 14:41:49 +01:00
Christopher Faulet
dbe57794c4 MINOR: mux-h1: Add a idle expiration date on the H1 connection
An idle expiration date is added on the H1 connection with the function to
set it depending on connection state. First, there is no idle timeout on
backend connections, For idle frontend connections, the http-request or
keep-alive timeout are used depending on which timeout is defined and if it
is the first request or not. For embryonic connections, the http-request is
always used, if defined. For attached or shutted down connections, no idle
timeout is applied.

For now the idle expiration date is never set and the h1_set_idle_expiration
function remains unused.
2020-12-04 14:41:49 +01:00
Christopher Faulet
5d3c93cd43 MINOR: mux-h1: Process next request for IDLE connection only
When the conn-stream is detached for a H1 connection, there is no reason to
subscribe for reads or process pending input data if the connection is not
idle. Because, it means a shutdown is pending.
2020-12-04 14:41:49 +01:00
Christopher Faulet
adcd789d92 MINOR: mux-h1: Rework h1_refresh_timeout to be easier to read
Conditions to set a timeout on the H1C task have been simplified or at least
changed to rely on H1 connection flags. Now, following rules are used :

 * the shutdown timeout is applied on dead (not alive) or shutted down
   connections.

 * The client/server timeout is applied if there are still some pending
   outgoing data.

 * The client timeout is applied on alive frontend connections with no
   conn-stream. It means on idle or embryionic frontend connections.

 * For all other connections (backend or attached connections), no timeout
   is applied. For frontend or backend attached connections, the timeout is
   handled by the application layer. For idle backend connections, there is
   no timeout.
2020-12-04 14:41:49 +01:00
Christopher Faulet
3c82d8b328 MINOR: mux-h1: Rework how shutdowns are handled
We now only rely on one flag to notify a shutdown. The shutdown is performed
at the connection level when there are no more pending outgoing data. So, it
means it is performed immediately if the output buffer is empty. Otherwise
it is deferred after the outgoing data are sent.

This simplify a bit the mux because there is now only one flag to check.
2020-12-04 14:41:49 +01:00
Christopher Faulet
119ac870ce MINOR: mux-h1: Disable reads if an error was reported on the H1 stream
Don't try to read more data if a parsing or a formatting error was reported
on the H1 stream. There is no reason to continue to process the messages for
the current connection in this case. If a parsing error occurs, it means the
input is invalid. If a formatting error occurs, it is an internal error and
it is probably safer to give up.
2020-12-04 14:41:49 +01:00
Christopher Faulet
295b8d1649 MINOR: mux-h1: Reset more H1C flags when a H1 stream is destroyed
When a H1 stream is destroyed, all dynamic flags on the H1 connection are
reset to be sure to leave it in a clean state.
2020-12-04 14:41:49 +01:00
Christopher Faulet
c1c66a4759 MINOR: mux-h1: rework the h1_timeout_task() function
Mainly to make it easier to read. First of all, when a H1 connection is
still there, we check if the connection was stolen by another thread or
not. If yes we release the task and leave. Then we check if the task is
expired or not. Only expired tasks are considered. Finally, if a conn-stream
is still attached to the connection (H1C_F_CS_ATTACHED flag set), we
return. Otherwise, the task and the H1 connection are released.
2020-12-04 14:41:48 +01:00
Christopher Faulet
bb8baf477d MINOR: mux-h1: Add embryonic and attached states on the H1 connection
Be prepared to have a H1 connection in one of the following states :

 * A H1 connection waiting for a new message with no H1 stream.
   H1C_F_CS_IDLE flag is set.

 * A H1 connection processing a new message with a H1 stream but no
   conn-stream attached. H1C_F_CS_EMBRYONIC flag is set

 * A H1 connection with a H1 stream and a conn-stream attached.
   H1C_F_CS_ATTACHED flag is set.

 * A H1 connection with no H1 stream, waiting to be released. No flag is set.

These flags are mutually exclusives. When none is set, it means the
connection will be released ASAP, just remaining outgoing data must be sent
before. For now, the second state (H1C_F_CS_EMBRYONIC) is transient.
2020-12-04 14:41:48 +01:00
Christopher Faulet
a583af6333 MINOR: mux-h1: Don't set CS flags in internal parsing functions
Now, only h1_process_input() function set or unset the conn-stream
flags. This way, internal parsing functions don't rely anymore on the
conn-stream.
2020-12-04 14:41:48 +01:00
Christopher Faulet
d17ad8214f MINOR: mux-h1: Add a rxbuf into the H1 stream
For now this buffer is not used. But it will be used to parse the headers,
and possibly the first block of data, when no stream is attached to the H1
connection. The aim is to use it to create the stream, thanks to recent
changes on the streams creation api.
2020-12-04 14:41:48 +01:00
Christopher Faulet
2f0ec66613 MINOR: mux-h1: Split front/back h1 stream creation in 2 functions
Dedicated functions are now used to create frontend and backend H1
streams. h1c_frt_stream_new() is now used to create frontend H1 streams and
h1c_bck_stream_new() to create backend ones. Both rely on h1s_new() function
to allocate the stream itself. It is a bit easier to add specific processing
depending we are on the frontend or the backend side.
2020-12-04 14:41:48 +01:00
Christopher Faulet
60ef12c80b MINOR: mux-h1: Separate parsing and formatting errors at H1 stream level
Instead of using H1S flags to report an error on the request or the
response, independently it is a parsing or a formatting error, we now use a
flag to report parsing errors and another one to report formatting
ones. This simplify the message parsing. It is also easier to figure out
what error happened when one of this flag is set. The side may be deduced
checking the H1C_F_IS_BACK flag.
2020-12-04 14:41:48 +01:00
Christopher Faulet
0a799aa3d6 MINOR: mux-h1: Introduce H1C_F_IS_BACK flag on the H1 connection
This flag is only set on the backend side and is tested instead of calling
conn_is_back() function.
2020-12-04 14:41:48 +01:00
Christopher Faulet
ae635766f6 MEDIUM: mux-h1: Use a h1c flag to block reads when splicing is in-progress
Instead of using 2 flags on the H1 stream (H1S_F_BUF_FLUSH and
H1S_F_SPLICED_DATA), we now only use one flag on the H1 connection
(H1C_F_WANT_SPLICE) to notify we want to use splicing or we are using
splicing. This flag blocks the calls to rcv_buf() connection callback.

It is a bit easier to set the H1 connection capability to receive data in
its input buffer instead of relying on the H1 stream.
2020-12-04 14:41:48 +01:00
Christopher Faulet
089acd5b0d MINOR: mux-h1: Add a flag to disable reads to wait opposite side
H1C_F_WAIT_OPPOSITE must be set on the H1 conenction to don't read more data
because we must be sync with the opposite side. This flag replaces the
H1C_F_IN_BUSY flag. Its name is a bit explicit. It is automatically set on
the backend side when the mux is created. It is safe to do so because at
this stage, the request has not yet been sent to the server. This way, in
h1_recv_allowed(), a test on this flag is enough to block the reads instead
of testing the H1 stream state on the backend side.
2020-12-04 14:41:48 +01:00
Christopher Faulet
26256f86e1 MINOR: stream: Pass an optional input buffer when a stream is created
It is now possible to set the buffer used by the channel request buffer when
a stream is created. It may be useful if input data are already received,
instead of waiting the first call to the mux rcv_buf() callback. This change
is mandatory to support H1 connection with no stream attached.

For now, the multiplexers don't pass any buffer. BUF_NULL is thus used to
call stream_create_from_cs().
2020-12-04 14:41:48 +01:00
Christopher Faulet
3b536a3131 MINOR: mux-h1: Don't provide anymore timing info using cs_info structure
The cs_info are now unused. The stream uses the session to get these
info. So we can safely remove it from the mux-h1.
2020-12-04 14:41:48 +01:00
Christopher Faulet
15e525f495 MINOR: stream: Don't retrieve anymore timing info from the mux csinfo
These info are only provided by the mux-h1. But, thanks to previous patches,
we can get them from the session directly. There is no need to retrieve them
from the mux anymore.
2020-12-04 14:41:48 +01:00
Christopher Faulet
7a6c513246 MINOR: stream: Always get idle duration from the session
Since the idle duration provided by the session is always up-to-date, there
is no more reason to rely on the multiplexer cs_info to set it to the
stream.
2020-12-04 14:41:48 +01:00
Christopher Faulet
dd78921c66 MINOR: logs: Use session idle duration when no stream is provided
When a log message is emitted from the session, using sess_log() function,
there is no stream available. In this case, instead of deducing the idle
duration from the accept date, we use the one provided by the session. 0 is
used if it is undefined (i.e set to -1).
2020-12-04 14:41:48 +01:00
Christopher Faulet
42849b047a MINOR: mux-h1: Reset session dates and durations info when the CS is detached
These info are reset for the next transaction, if the connection is kept
alive. From the stream point of view, it should be the same a new
connection, except there is no handshake. Thus the handshake duration is set
to 0.
2020-12-04 14:41:48 +01:00
Christopher Faulet
4e74155466 MINOR: mux-h1: Update session idle duration when data are received
The session idle duration is set if not already done when data are
received. For now, this value is still unused.
2020-12-04 14:41:48 +01:00
Christopher Faulet
d517396f8e MINOR: session: Add the idle duration field into the session
The idle duration between two streams is added to the session structure. It
is not necessarily pertinent on all protocols. In fact, it is only defined
for H1 connections. It is the duration between two H1 transactions. But the
.get_cs_info() callback function on the multiplexers only exists because
this duration is missing at the session level. So it is a simplification
opportunity for a really low cost.

To reduce the cost, a hole in the session structure is filled by moving
.srv_list field at the end of the structure.
2020-12-04 14:41:48 +01:00
Christopher Faulet
268c92e2f8 BUG/MINOR: mux-h1: Handle keep-alive timeout for idle frontend connections
IDLE frontend connections have no stream attached. The stream is only
created when new data are received, when the parsing of the next request
starts. Thus the keep-alive timeout, handled into the HTTP analysers, is not
considered while nothing is received. But this is especially when this
timeout must be considered. Concretely the http-keep-alive is ignored while
no data are received. Only the client timeout is used. It will only be
considered on incomplete requests, if the http-request timeout is not set.

To fix the bug, the http-keep-alive timeout must be handled at the mux
level, for IDLE frontend connection only.

This patch should fix the issue #984. It must be backported as far as
2.2. On prior versions, the stream is created earlier. So, it is not a
problem, except if this behavior changes of course (it was an optim of the
2.2, but don't remember the commit).
2020-12-04 14:41:48 +01:00
Willy Tarreau
7da02dd308 BUG/MINOR: listener: use sockaddr_in6 for IPv6
A copy-paste bug between {tcp,udp}{4,6}_add_listener() resulted in
using a struct sockaddr_in to set the TCP/UDP port while it ought to
be a struct sockaddr_in6. Fortunately, the port has the same offset
(2) in both so it was harmless. A cleaner way to proceed would be
to have a set_port function exported by the address family layer.

This needs to be backported to 2.3.
2020-12-04 14:28:23 +01:00
Willy Tarreau
186f37674c BUG/MINOR: lua-thread: close all states on deinit
It seems to me that lua_close() must be called on all states at deinit
time, not just the first two ones. This is likely a remnant of commit
59f11be43 ("MEDIUM: lua-thread: Add the lua-load-per-thread directive").
There should likely be some memory leak reports when using Lua without
this fix, though none were observed for now.

No backport is needed as this was merged into 2.4-dev.
2020-12-04 12:00:11 +01:00
Thierry Fournier
aafc777854 BUG/MEDIUM: lua-thread: some parts must be initialized once
Lua dedicated TCP, HTTP and SSL socket and proxies must be initialized
once. Right now, they are initialized from the Lua init state, but since
commit 59f11be43 ("MEDIUM: lua-thread: Add the lua-load-per-thread
directive") this function is called one time per lua context. This
caused some fields to be cleared and overwritten, and pre-allocated
object to be lost. This is why the address sanitizer detected memory
leaks from the socket_ssl server initialization.

Let's move all the state-independent part of the function to the
hlua_init() function to avoid this.

No backport is needed, this is only 2.4-dev.
2020-12-04 11:55:05 +01:00
Remi Tricot-Le Breton
51058d64a6 MINOR: cache: Consider invalid Age values as stale
Do not store responses that have an invalid age header (non numerical,
negative ...).
2020-12-04 10:21:56 +01:00
Remi Tricot-Le Breton
72cffaf440 MEDIUM: cache: Remove cache entry in case of POST on the same resource
In case of successful unsafe method on a stored resource, the cached entry
must be invalidated (see RFC7234#4.4).
A "non-error response" is one with a 2xx (Successful) or 3xx (Redirection)
status code.
This implies that the primary hash must now be calculated on requests
that have an unsafe method (POST or PUT for instance) so that we can
disable the corresponding entries when we process the response.
2020-12-04 10:21:56 +01:00
Remi Tricot-Le Breton
fcea374fdf MINOR: cache: Add extra "cache-control" value checks
The Cache-Control max-age and s-maxage directives should be followed by
a positive numerical value (see RFC 7234#5.2.1.1). According to the
specs, a sender "should not" generate a quoted-string value but we will
still accept this format.
2020-12-04 10:21:56 +01:00
Remi Tricot-Le Breton
795e1412b0 MINOR: cache: Do not store stale entry
When a response has an Age header (filled in by another cache on the
message's path) that is greater than its defined maximum age (extracted
either from cache-control directives or an expires header), it is
already stale and should not be cached.
2020-12-04 10:21:56 +01:00
David Carlier
2d0493af49 BUILD/MINOR: haproxy DragonFlyBSD affinity build update.
sched_setaffinity supported by this platform.
2020-12-02 22:43:57 +01:00
Thierry Fournier
46278ff828 MINOR: lua-thread: Add verbosity in errors
Because lua-load-per-thread could not load the same code for each thread,
this patch displays the state-id associated with the error.
2020-12-02 21:53:16 +01:00
Thierry Fournier
59f11be436 MEDIUM: lua-thread: Add the lua-load-per-thread directive
The goal is to allow execution of one main lua state per thread.

This patch contains the main job. The lua init is done using these
steps:
 - "lua-load-per-thread" loads the lua code in the first thread
 - it creates the structs
 - it stores loaded files
 - the 1st step load is completed (execution of hlua_post_init)
   and now, we known the number of threads
 - we initilize lua states for all remaining threads
 - for each one, we load the lua file
 - for each one, we execute post-init

Once all is loaded, we control consistency of functions references.
The rules are:
 - a function reference cannot be in the shared lua state and in
   a per-thread lua state at the same time.
 - if a function reference is declared in a per-thread lua state, it
   must be declared in all per-thread lua states
2020-12-02 21:53:16 +01:00
Thierry Fournier
c749259dff MINOR: lua-thread: Store each function reference and init reference in array
The goal is to allow execution of one main lua state per thread.

The array introduces storage of one reference per thread, because each
lua state can have different reference id for a same function. A function
returns the preferred state id according to configuration and current
thread id.
2020-12-02 21:53:16 +01:00
Thierry Fournier
021d986ecc MINOR: lua-thread: Replace state_from by state_id
The goal is to allow execution of one main lua state per thread.

"state_from" is a pointer to the parent lua state. "state_id"
is the index of the parent state id in the reference lua states
array. "state_id" is better because the lock is a "== 0" test
which is quick than pointer comparison. In other way, the state_id
index could index other things the the Lua state concerned. I
think to the function references.
2020-12-02 21:53:16 +01:00
Thierry Fournier
62a22aa23f MINOR: lua-thread: Replace "struct hlua_function" allocation by dedicated function
The goal is to allow execution of one main lua state per thread.

This function will initialize the struct with other things than 0.
With this function helper, the initialization is centralized and
it prevents mistakes. This patch also keeps a reference to each
declared function in a list. It will be useful in next patches to
control consistency of declared references.
2020-12-02 21:53:16 +01:00
Thierry Fournier
afc63e2cb1 MINOR: lua-thread: Replace global gL var with an array of states
The goal is to allow execution of one main lua state per thread.

The array of states is initialized at the max number of thread +1.
We define the index 0 is the common state shared by all threads
and should be locked. Other index index are dedicated to each
one thread. The old gL now becomes hlua_states[0].
2020-12-02 21:53:16 +01:00
Thierry Fournier
7cbe5046e8 MEDIUM: lua-thread: Apply lock only if the parent state is the main thread
The goal is to allow execution of one main lua state per thread.

This patch opens the way to addition of a per-thread dedicated lua state.
By passing the hlua we can figure the original state that's been used
and decide to lock or not.
2020-12-02 21:53:16 +01:00
Thierry Fournier
3c539327f4 MEDIUM: lua-thread: No longer use locked context in initialization parts
The goal is to allow execution of one main lua state per thread.

Stop using locks in init part, we will use only in parts where
the parent lua state is known, so we could take decision about lock
according with the lua parent state.
2020-12-02 21:53:16 +01:00
Thierry Fournier
ecb83c24c4 MINOR: lua-thread: Add the "thread" core variable
The goal is to allow execution of one main lua state per thread.

This commit introduces this variable in the core. Lua state initialized
by thread will have access to this variable, which reports the executing
thread. 0 indicates the shared thread. Programs which must be executed
only once can check for core.thread <= 1.
2020-12-02 21:53:16 +01:00
Thierry Fournier
b8cef175bd MINOR: lua-thread: Split hlua_post_init() function in two parts
The goal is to allow execution of one main lua state per thread.

This function will be called for each initialized lua state, so
one per thread. The split transforms the lua state variable from
global to local.
2020-12-02 21:53:16 +01:00
Thierry Fournier
c93c15cf8c MINOR: lua-thread: Split hlua_load function in two parts
The goal is to allow execution of one main lua state per thread.

This function will be called once per thread, using different Lua
states. This patch prepares the work.
2020-12-02 21:53:16 +01:00
Thierry Fournier
75fc02956b MINOR: lua-thread: make hlua_ctx_init() get L from its caller
The goal is to allow execution of one main lua state per thread.

The function hlua_ctx_init() now gets the original lua state from
its caller. This allows the initialisation of lua_thread (coroutines)
from any master lua state.

The parent lua state is stored in the hlua struct.

This patch is a temporary transition, it will be modified later.
2020-12-02 21:53:16 +01:00
Thierry Fournier
1eac28f5fc MINOR: lua-thread: Split hlua_init() function in two parts
The goal is to allow execution of one main lua state per thread.

This is a preparative work in order to init more than one stack
in the lua-thread objective.
2020-12-02 21:53:16 +01:00
Thierry Fournier
ad5345fed7 MINOR: lua-thread: Replace embedded struct hlua_function by a pointer
The goal is to allow execution of one main lua state per thread.

Because this struct will be filled after the configuration parser, we
cannot copy the content. The actual state of the Haproxy code doesn't
justify this change, it is an update preparing next steps.
2020-12-02 21:53:16 +01:00
Thierry Fournier
92689e651e MINOR: lua-thread: Stop usage of struct hlua for the global lua state
The goal is to no longer use "struct hlua" with global main lua_state.

The usage of the "struct hlua" is no longer required. This patch replaces
this struct by another one.

Now, the usage of runtime Lua phase is separated from the start lua phase.
2020-12-02 21:53:16 +01:00
Thierry Fournier
4234dbd03b MINOR: lua-thread: Use NULL context for main lua state
The goal is to no longer use "struct hlua" with global main lua_state.

This patch returns NULL value when some code tries go get the hlua struct
associated with a task through hlua_gethlua(). This functions is useful
only during runtime because the struct hlua contains only runtime states.

Some Lua functions allowed to yield are called from init environment.
I'm not sure this is a good practice. Maybe it will be clever to
disallow calling this kind of functions.
2020-12-02 21:53:16 +01:00
Thierry Fournier
9eb3230b7c MINOR: lua-thread: hlua_ctx_renew() is never called with main gL lua state
The goal is no longer using "struct hlua" with global main lua_state.

if somewhere in the code, hlua_ctx_renew() is called with a global Lua
context, we have a serious bug. A crash is better than working with
this bug, so this patch remove a useless control.

In other way, this control were used during hlua_post_init() function.
The function hlua_post_init() used a call to the runtime hlua_ctx_resume()
function. This call no longer exists.
2020-12-02 21:53:16 +01:00
Thierry Fournier
670db24329 MEDIUM: lua-thread: make hlua_post_init() no longer use the runtime execution function
The goal is to no longer use "struct hlua" with global main lua_state.

The hlua_post_init() is executed during start phase, it does not require
yielding nor any advanced runtime error processing. Let's simplify this
by re-implementing the code using lower-level functions which directly
take a state and not an hlua anymore.
2020-12-02 21:53:16 +01:00
Thierry Fournier
3fb9e5133a MINOR: lua-thread: remove struct hlua from function hlua_prepend_path()
The goal is to no longer use "struct hlua" with global main lua_state
and directly take the state instead.

This patch removes the implicit dependency to this struct with
the function hlua_prepend_path()
2020-12-02 21:53:16 +01:00
Willy Tarreau
cdb53465f4 MEDIUM: lua-thread: use atomics for memory accounting
Let's switch memory accounting to atomics so that the allocator function
may safely be used from concurrent Lua states.

Given that this function is extremely hot on the call path, we try to
optimize it for the most common case, which is:
  - no limit
  - there's enough memory

The accounting is what is particuarly expensive in threads since all
CPUs compete for a cache line, so when the limit is not used, we don't
want to use accounting. However we need to preserve it during the boot
phase until we may parse a "tune.lua.maxmem" value. For this, we turn
the unlimited "0" value to ~0 at the end of the boot phase to mark the
definite end of accounting. The function then detects this value and
directly jumps to realloc() in this case.

When the limit is enforced however, we use a CAS to check and reserve
our share of memory, and we roll back on failure. The CAS is used both
for increments and decrements so that a single operation is enough to
update the counters.
2020-12-02 21:53:16 +01:00
Willy Tarreau
d36c7fa5ec MINOR: lua: simplify hlua_alloc() to only rely on realloc()
The function really has the semantics of a realloc() except that it
also passes the old size to help with accounting. No need to special
case the free or malloc, realloc does everything we need.
2020-12-02 21:53:16 +01:00
Emeric Brun
fdabf49548 BUG/MAJOR: ring: tcp forward on ring can break the reader counter.
If the session is not established, the applet handler could leave
with the applet detached from the ring. At next call, the attach
counter will be decreased again causing unpredectable behavior.

This patch should be backported on branches >=2.2
2020-12-02 20:17:19 +01:00
Frdric Lcaille
fd1831499e BUG/MINOR: trace: Wrong displayed trace level
With commit a1f12746b ("MINOR: traces: add a new level "error" below
the "user" level") a new trace level was inserted, resulting in
shifting all exiting ones by one. But the levels reported in the
__trace() function were not updated accordingly, resulting in the
TRACE_LEVEL_DEVELOPER not to be properly reported anymore. This
patch fixes it by extending the number of levels to 6.

No backport is needed.
2020-12-02 17:44:40 +01:00
Remi Tricot-Le Breton
3243447f83 MINOR: cache: Add entry to the tree as soon as possible
When many concurrent requests targeting the same resource were seen, the
cache could sometimes be filled by too many partial responses resulting
in the impossibility to cache a single one of them. This happened
because the actual tree insertion happened only after all the payload of
every response was seen. So until then, every response was added to the
cache because none of the streams knew that a similar request/response
was already being treated.
This patch consists in adding the cache_entry as soon as possible in the
tree (right after the first packet) so that the other responses do not
get cached as well (if they have the same primary key).
A "complete" flag is also added to the cache_entry so that we know if
all the payload is already stored in the entry or if it is still being
processed.
2020-12-02 16:38:42 +01:00
Remi Tricot-Le Breton
8bb72aa82f MINOR: cache: Improve accept_encoding_normalizer
Turn the "Accept-Encoding" value to lower case before processing it.
Calculate the CRC on every token instead of a sorted concatenation of
them all (in order to avoir copying them) then XOR all the CRCs into a
single hash (while ignoring duplicates).
2020-12-02 16:32:54 +01:00
Thierry Fournier
f67442efdb BUG/MINOR: lua: warn when registering action, conv, sf, cli or applet multiple times
Lua allows registering multiple sample-fetches, converters, action, cli,
applet/services with the same name. This is absolutely useless since only
the first registration will be used. This patch sends a warning if the case
is encountered.

This pach could be backported until 1.8, with the 3 associated patches:
 - MINOR: actions: Export actions lookup functions
 - MINOR: actions: add a function returning a service pointer from its name
 - MINOR: cli: add a function to look up a CLI service description
2020-12-02 09:45:18 +01:00
Thierry Fournier
a51a1fd174 MINOR: cli: add a function to look up a CLI service description
This function will be useful to check if the keyword is already registered.
Also add a define for the max number of args.

This will be needed by a next patch to fix a bug and will have to be
backported.
2020-12-02 09:45:18 +01:00
Thierry Fournier
87e539906b MINOR: actions: add a function returning a service pointer from its name
This function simply calls action_lookup() on the private service_keywords,
to look up a service name. This will be used to detect double registration
of a same service from Lua.

This will be needed by a next patch to fix a bug and will have to be
backported.
2020-12-02 09:45:18 +01:00
Thierry Fournier
7a71a6d9d2 MINOR: actions: Export actions lookup functions
These functions will be useful to check if a keyword is already registered.
This will be needed by a next patch to fix a bug, and will need to be
backported.
2020-12-02 09:45:18 +01:00
Thierry Fournier
2f05cc6f86 BUG/MINOR: lua: Some lua init operation are processed unsafe
Operation luaL_openlibs() and lua_prepend path are processed whithout
the safe context, so in case of failure Haproxy aborts or stops without
error message.

This patch could be backported until 1.8
2020-12-02 09:45:18 +01:00
Thierry Fournier
13d08b73eb BUG/MINOR: lua: Post init register function are not executed beyond the first one
Just because if the first init is a success we return success in place
of continuing the loop.

This patch could be backported until 1.8
2020-12-02 09:45:18 +01:00
Thierry Fournier
77a88943d6 BUG/MINOR: lua: lua-load doesn't check its parameters
"lua-load" doesn't check if the expected parameter is present. It tries to
open() directly the argument at second position. So if the filename is
omitted, it tries to load an empty filename.

This patch could be backported until 1.8
2020-12-02 09:42:43 +01:00
Thierry Fournier
de6145f747 BUG/MINOR: lua: missing "\n" in error message
Just replace ".n" by "\n"

This could be backported until 1.9, but it is not so important.
2020-12-02 09:31:33 +01:00
Willy Tarreau
f965b2ad13 BUG/MINOR: mux-h2/stats: not all GOAWAY frames are errors
The stats on haproxy.org reported ~12k GOAWAY for ~34k connections, with
only 2 protocol errorss. It turns out that the GOAWAY frame counter added
in commit a8879238c ("MINOR: mux-h2: report detected error on stats")
matches a bit too many situations. First it counts those which are not
sent as well as failed retries, second it counts as errors the cases of
attempts to cleanly close, while it's titled "GOAWAY sent on detected
error". Let's address this by moving the counter up one line and excluding
the clean codes.

This can be backported to 2.3.
2020-12-01 10:47:18 +01:00
Willy Tarreau
5dd36ac8a0 MINOR: mux-h2/trace: add traces at level ERROR for protocol errors
A number of traces could be added, and a few TRACE_PROTO were replaced
with TRACE_ERROR. The goal is to be able to enable error tracing only
to detect anomalies.

It looks like they're mostly correct as they don't seem to strike on
valid H2 traffic but are very verbose on h2spec.
2020-12-01 10:30:37 +01:00
Willy Tarreau
a1f12746b1 MINOR: traces: add a new level "error" below the "user" level
Sometimes it would be nice to be able to only trace abnormal events such
as protocol errors. Let's add a new "error" level below the "user" level
for this. This will allow to add TRACE_ERROR() at various error points
and only see them.
2020-12-01 10:25:20 +01:00
Willy Tarreau
a307528fe2 BUG/MINOR: mux-h2/stats: make stream/connection proto errors more accurate
Since commit a8879238c ("MINOR: mux-h2: report detected error on stats")
we now have some error stats on stream/connection level protocol errors,
but some were improperly marked as stream while they're connection, and
2 or 3 relevant ones were missing and have now been added.

This could be backported to 2.3.
2020-12-01 10:25:20 +01:00
Maciej Zdeb
fcdfd857b3 MINOR: log: Logging HTTP path only with %HPO
This patch adds a new logging variable '%HPO' for logging HTTP path only
(without query string) from relative or absolute URI.

For example:
log-format "hpo=%HPO hp=%HP hu=%HU hq=%HQ"

GET /r/1 HTTP/1.1
=>
hpo=/r/1 hp=/r/1 hu=/r/1 hq=

GET /r/2?q=2 HTTP/1.1
=>
hpo=/r/2 hp=/r/2 hu=/r/2?q=2 hq=?q=2

GET http://host/r/3 HTTP/1.1
=>
hpo=/r/3 hp=http://host/r/3 hu=http://host/r/3 hq=

GET http://host/r/4?q=4 HTTP/1.1
=>
hpo=/r/4 hp=http://host/r/4 hu=http://host/r/4?q=4 hq=?q=4
2020-12-01 09:32:44 +01:00
Emeric Brun
0237c4e3f5 BUG/MEDIUM: local log format regression.
Since 2.3 default local log format always adds hostame field.
This behavior change was due to log/sink re-work, because according
to rfc3164 the hostname field is mandatory.

This patch re-introduce a legacy "local" format which is analog
to rfc3164 but with hostname stripped. This is the new
default if logs are generated by haproxy.

To stay compliant with previous configurations, the option
"log-send-hostname" acts as if the default format is switched
to rfc3164.

This patch addresses the github issue #963

This patch should be backported in branches >= 2.3.
2020-12-01 06:58:42 +01:00
Willy Tarreau
4d6c594998 BUG/MEDIUM: task: close a possible data race condition on a tasklet's list link
In issue #958 Ashley Penney reported intermittent crashes on AWS's ARM
nodes which would not happen on x86 nodes. After investigation it turned
out that the Neoverse N1 CPU cores used in the Graviton2 CPU are much
more aggressive than the usual Cortex A53/A72/A55 or any x86 regarding
memory ordering.

The issue that was triggered there is that if a tasklet_wakeup() call
is made on a tasklet scheduled to run on a foreign thread and that
tasklet is just being dequeued to be processed, there can be a race at
two places:
  - if MT_LIST_TRY_ADDQ() happens between MT_LIST_BEHEAD() and
    LIST_SPLICE_END_DETACHED() if the tasklet is alone in the list,
    because the emptiness tests matches ;

  - if MT_LIST_TRY_ADDQ() happens during LIST_DEL_INIT() in
    run_tasks_from_lists(), then depending on how LIST_DEL_INIT() ends
    up being implemented, it may even corrupt the adjacent nodes while
    they're being reused for the in-tree storage.

This issue was introduced in 2.2 when support for waking up remote
tasklets was added. Initially the attachment of a tasklet to a list
was enough to know its status and this used to be stable information.
Now it's not sufficient to rely on this anymore, thus we need to use
a different information.

This patch solves this by adding a new task flag, TASK_IN_LIST, which
is atomically set before attaching a tasklet to a list, and is only
removed after the tasklet is detached from a list. It is checked
by tasklet_wakeup_on() so that it may only be done while the tasklet
is out of any list, and is cleared during the state switch when calling
the tasklet. Note that the flag is not set for pure tasks as it's not
needed.

However this introduces a new special case: the function
tasklet_remove_from_tasklet_list() needs to keep both states in sync
and cannot check both the state and the attachment to a list at the
same time. This function is already limited to being used by the thread
owning the tasklet, so in this case the test remains reliable. However,
just like its predecessors, this function is wrong by design and it
should probably be replaced with a stricter one, a lazy one, or be
totally removed (it's only used in checks to avoid calling a possibly
scheduled event, and when freeing a tasklet). Regardless, for now the
function exists so the flag is removed only if the deletion could be
done, which covers all cases we're interested in regarding the insertion.
This removal is safe against a concurrent tasklet_wakeup_on() since
MT_LIST_DEL() guarantees the atomic test, and will ultimately clear
the flag only if the task could be deleted, so the flag will always
reflect the last state.

This should be carefully be backported as far as 2.2 after some
observation period. This patch depends on previous patch
"MINOR: task: remove __tasklet_remove_from_tasklet_list()".
2020-11-30 18:17:59 +01:00
Willy Tarreau
2da4c316c2 MINOR: task: remove __tasklet_remove_from_tasklet_list()
This function is only used at a single place directly within the
scheduler in run_tasks_from_lists() and it really ought not be called
by anything else, regardless of what its comment says. Let's delete
it, move the two lines directly into the call place, and take this
opportunity to factor the atomic decrement on tasks_run_queue. A comment
was added on the remaining one tasklet_remove_from_tasklet_list() to
mention the risks in using it.
2020-11-30 18:17:44 +01:00
Willy Tarreau
c309dbdd99 MINOR: task: perform atomic counter increments only once per wakeup
In process_runnable_tasks(), we walk the run queue and pick tasks to
insert them into the local list. And for each of these operations we
perform a few increments, some of which are atomic, and they're even
performed under the runqueue's lock. This is useless inside the loop,
better do them at the end, since we don't use these values inside the
loop and they're not used anywhere else either during this time. The
only one is task_list_size which is accessed in parallel by other
threads performing remote tasklet wakeups, but it's already
approximative and is used to decide to get out of the loop when the
limit is reached. So now we compute it first as an initial budget
instead.
2020-11-30 18:17:44 +01:00
Willy Tarreau
a868c2920b MINOR: task: remove tasklet_insert_into_tasklet_list()
This function is only called at a single place and adds more confusion
than it removes. It also makes one think it could be used outside of
the scheduler while it must absolutely not. Let's just move its two
lines to the call place, making the code more readable there. In
addition this clearly shows that the preliminary LIST_INIT() is
useless since the entry is immediately overwritten.
2020-11-30 18:17:44 +01:00
Willy Tarreau
8a069eb9a4 MINOR: debug: add a trivial PRNG for scheduler stress-tests
Commit a5a447984 ("MINOR: debug: add "debug dev sched" to stress the
scheduler.") doesn't scale with threads because ha_random64() takes care
of being totally thread-safe for use with UUIDs. We don't need this for
the stress-testing functions, let's just implement a xorshift PRNG
instead. On 8 threads the performance jumped from 230k ctx/s with 96%
spent in ha_random64() to 14M ctx/s.
2020-11-30 17:07:32 +01:00
Willy Tarreau
a5a4479849 MINOR: debug: add "debug dev sched" to stress the scheduler.
This command supports starting a bunch of tasks or tasklets, either on the
current thread (mask=0), all (default), or any set, either single-threaded
or multi-threaded, and possibly auto-scheduled.

These tasks/tasklets will randomly pick another one to wake it up. The
tasks only do it 50% of the time while tasklets always wake two tasks up,
in order to achieve roughly 50% load (since the target might already be
woken up).
2020-11-29 17:43:07 +01:00
Christopher Faulet
a9ffc41637 BUG/MINOR: http-fetch: Fix smp_fetch_body() when called from a health-check
res.body may be called from a health-check. It is probably never used. But it is
possibe. In such case, there is no channel. Thus we must not use it
unconditionally to set the flag SMP_F_MAY_CHANGE on the smp.

Now the condition test the channel first. In addtion, the flag is not set if the
payload is fully received.

This patch must be backported as far as 2.2.
2020-11-27 10:30:23 +01:00
Christopher Faulet
83662b5431 MINOR: tcpcheck: Add support of L7OKC on expect rules error-status argument
L7OKC may now be used as an error status for an HTTP/TCP expect rule. Thus
it is for instance possible to write:

    option httpchk GET /isalive
    http-check expect status 200,404
    http-check expect status 200 error-status L7OKC

It is more or less the same than the disable-on-404 option except that if a
DOWN is up again but still replying a 404 will be set to NOLB state. While
it will stay in DOWN state with the disable-on-404 option.
2020-11-27 10:30:23 +01:00
Christopher Faulet
1e527cbf53 MINOR: check: Always increment check health counter on CONPASS
Regarding the health counter, a check finished with the CONDPASS result is
now the same than with the PASSED result: The health counter is always
incemented. Before, it was only performed is the health counter was not 0.

There is no change for the disable-on-404 option because it is only
evaluated for running or stopping servers. So with an health check counter
greater than 0. But it will make possible to handle (STOPPED -> STOPPING)
transition for servers.
2020-11-27 10:30:23 +01:00
Christopher Faulet
97b7bdfcf7 REORG: tcpcheck: Move check option parsing functions based on tcp-check
The parsing of the check options based on tcp-check rules (redis, spop,
smtp, http...) are moved aways from check.c. Now, these functions are placed
in tcpcheck.c. These functions are only related to the tcpcheck ruleset
configured on a proxy and not to the health-check attached to a server.
2020-11-27 10:30:23 +01:00
Christopher Faulet
f8c869bac4 MINOR: config: Add a warning if tune.chksize is used
This option is now deprecated. It is recent, but it is now marked as
deprecated as far as 2.2. Thus, there is now a warning in the 2.4 if this
option is still used. It will be removed in 2.5.

Becaue the 2.3 is quite new, this patch may be backported to 2.3.
2020-11-27 10:30:23 +01:00
Christopher Faulet
bb9fb8b7f8 MINOR: config: Deprecate and ignore tune.chksize global option
This option is now ignored because I/O check buffers are now allocated using the
buffer pool. Thus, it is marked as deprecated in the documentation and ignored
during the configuration parsing. The field is also removed from the global
structure.

Because this option is ignored since a recent fix, backported as fare as 2.2,
this patch should be backported too. Especially because it updates the
documentation.
2020-11-27 10:30:23 +01:00
Christopher Faulet
b1bb069c15 MINOR: tcpcheck: Don't handle anymore in-progress connect rules in tcpcheck_main
The special handling of in-progress connect rules at the begining of
tcpcheck_main() function can be removed. Instead, at the begining of the
tcpcheck_eval_connect() function, we test is there is already an existing
connection. In this case, it means we are waiting for a connection
establishment. In addition, before evaluating a new connect rule, we take
care to release any previous connection.
2020-11-27 10:29:41 +01:00
Christopher Faulet
b381a505c1 BUG/MAJOR: tcpcheck: Allocate input and output buffers from the buffer pool
Historically, the input and output buffers of a check are allocated by hand
during the startup, with a specific size (not necessarily the same than
other buffers). But since the recent refactoring of the checks to rely
exclusively on the tcp-checks and to use the underlying mux layer, this part
is totally buggy. Indeed, because these buffers are now passed to a mux,
they maybe be swapped if a zero-copy is possible. In fact, for now it is
only possible in h2_rcv_buf(). Thus the bug concretely only exists if a h2
health-check is performed. But, it is a latent bug for other muxes.

Another problem is the size of these buffers. because it may differ for the
other buffer size, it might be source of bugs.

Finally, for configurations with hundreds of thousands of servers, having 2
buffers per check always allocated may be an issue.

To fix the bug, we now allocate these buffers when required using the buffer
pool. Thus not-running checks don't waste memory and muxes may swap them if
possible. The only drawback is the check buffers have now always the same
size than buffers used by the streams. This deprecates indirectly the
"tune.chksize" global option.

In addition, the http-check regtest have been update to perform some h2
health-checks.

Many thanks to @VigneshSP94 for its help on this bug.

This patch should solve the issue #936. It relies on the commit "MINOR:
tcpcheck: Don't handle anymore in-progress send rules in tcpcheck_main".
Both must be backport as far as 2.2.

bla
2020-11-27 10:29:41 +01:00
Christopher Faulet
39066c2738 MINOR: tcpcheck: Don't handle anymore in-progress send rules in tcpcheck_main
The special handling of in-progress send rules at the begining of
tcpcheck_main() function can be removed. Instead, at the begining of the
tcpcheck_eval_send() function, we test is there is some data in the output
buffer. In this case, it means we are evaluating an unfinished send rule and
we can jump to the sending part, skipping the formatting part.

This patch is mandatory for a major fix on the checks and must be backported
as far as 2.2.
2020-11-27 10:08:21 +01:00
Christopher Faulet
1faf18ae39 BUG/MINOR: tcpcheck: Don't forget to reset tcp-check flags on new kind of check
When a new kind of check is found during the parsing of a proxy section (via
an option directive), we must reset tcpcheck flags for this proxy. It is
mandatory to not inherit some flags from a previously declared check (for
instance in the default section).

This patch must be backported as far as 2.2.
2020-11-27 10:08:18 +01:00
Willy Tarreau
5a7d6ebf2c MINOR: fd/threads: silence a build warning with threads disabled
Building with gcc-9.3.0 without threads may result in this warning:

In file included from include/haproxy/api-t.h:36,
                 from include/haproxy/api.h:33,
                 from src/fd.c:90:
src/fd.c: In function 'updt_fd_polling':
include/haproxy/fd.h:507:11: warning: array subscript 63 is above array bounds of 'int[1]' [-Warray-bounds]
  507 |  DISGUISE(write(poller_wr_pipe[tid], &c, 1));
include/haproxy/compiler.h:92:41: note: in definition of macro 'DISGUISE'
   92 | #define DISGUISE(v) ({ typeof(v) __v = (v); ALREADY_CHECKED(__v); __v; })
      |                                         ^
src/fd.c:113:5: note: while referencing 'poller_wr_pipe'
  113 | int poller_wr_pipe[MAX_THREADS]; // Pipe to wake the threads
      |     ^~~~~~~~~~~~~~

gcc is wrong but this time it cannot be blamed because it doesn't know
that the FD's thread_mask always has at least one bit set. Let's add
the test for all_threads_mask there. It will also remove that test and
drop the else block.
2020-11-26 22:28:41 +01:00
Willy Tarreau
345ebcfc01 BUG/MAJOR: peers: fix partial message decoding
Another bug in the peers message parser was uncovered by last commit
1dfd4f106 ("BUG/MEDIUM: peers: fix decoding of multi-byte length in
stick-table messages"): the function return on incomplete message does
not check if the channel has a pending close before deciding to return
0. It did not hurt previously because the loop calling co_getblk() once
per character would have depleted the buffer and hit the end, causing
<0 to be returned and matching the condition. But now that we process
at once what is available this cannot be relied on anymore and it's
now clearly visible that the final check is missing.

What happens when this strikes is that if a peer connection breaks in
the middle of a message, the function will return 0 (missing data) but
the caller doesn't check for the closed buffer, subscribes to reads,
and the applet handler is immediately called again since some data are
still available. This is detected by the loop prevention and the process
dies complaining that an appctx is spinning.

This patch simply adds the check for closed channel. It must be
backported to the same versions as the fix above.
2020-11-26 17:12:47 +01:00
Tim Duesterhus
23b2945c1c BUG/CRITICAL: cache: Fix trivial crash by sending accept-encoding header
Since commit 3d08236cb3 HAProxy can be trivially
crashed remotely by sending an `accept-encoding` HTTP request header that
contains 16 commas.

This is because the `values` array in `accept_encoding_normalizer` accepts only
16 entries and it is not verified whether the end is reached during looping.

Fix this issue by checking the length. This patch also simplifies the ist
processing in the loop, because it manually calculated offsets and lengths,
when the ist API exposes perfectly safe functions to advance and truncate ists.

I wonder whether the accept_encoding_normalizer function is able to re-use some
existing function for parsing headers that may contain lists of values. I'll
leave this evaluation up to someone else, only patching the obvious crash.

This commit is 2.4-dev specific and was merged just a few hours ago. No
backport needed.
2020-11-25 10:23:00 +01:00
Remi Tricot-Le Breton
754b2428d3 MINOR: cache: Add a process-vary option that can enable/disable Vary processing
The cache section's process-vary option takes a 0 or 1 value to disable
or enable the vary processing.
When disabled, a response containing such a header will never be cached.
When enabled, we will calculate a preliminary hash for a subset of request
headers on all the incoming requests (which might come with a cpu cost) which
will be used to build a secondary key for a given request (see RFC 7234#4.1).
The default value is 0 (disabled).
2020-11-24 16:52:57 +01:00
Remi Tricot-Le Breton
1785f3dd96 MEDIUM: cache: Add the Vary header support
Calculate a preliminary secondary key for every request we see so that
we can have a real secondary key if the response is cacheable and
contains a manageable Vary header.
The cache's ebtree is now allowed to have multiple entries with the same
primary key. Two of those entries will be distinguished thanks to
secondary keys stored in the cache_entry (based on hashes of a subset of
their headers).
When looking for an entry in the cache (cache_use), we still use the
primary key (built the same way as before), but in case of match, we
also need to check if the entry has a vary signature. If it has one, we
need to perform an extra check based on the newly built secondary key.
We will only be able to forge a response out of the cache if both the
primary and secondary keys match with one of our entries. Otherwise the
request will be forwarder to the server.
2020-11-24 16:52:57 +01:00
Remi Tricot-Le Breton
3d08236cb3 MINOR: cache: Prepare helper functions for Vary support
The Vary functionality is based on a secondary key that needs to be
calculated for every request to which a server answers with a Vary
header. The Vary header, which can only be found in server responses,
determines which headers of the request need to be taken into account in
the secondary key. Since we do not want to have to store all the headers
of the request until we have the response, we will pre-calculate as many
sub-hashes as there are headers that we want to manage in a Vary
context. We will only focus on a subset of headers which are likely to
be mentioned in a Vary response (accept-encoding and referer for now).
Every managed header will have its own normalization function which is
in charge of transforming the header value into a core representation,
more robust to insignificant changes that could exist between multiple
clients. For instance, two accept-encoding values mentioning the same
encodings but in different orders should give the same hash.
This patch adds a function that parses a Vary header value and checks if
all the values belong to our supported subset. It also adds the
normalization functions for our two headers, as well as utility
functions that can prebuild a secondary key for a given request and
transform it into an actual secondary key after the vary signature is
determined from the response.
2020-11-24 16:52:57 +01:00
Christopher Faulet
401e6dbff3 BUG/MAJOR: filters: Always keep all offsets up to date during data filtering
When at least one data filter is registered on a channel, the offsets of all
filters must be kept up to date. For data filters but also for others. It is
safer to do it in that way. Indirectly, this patch fixes 2 hidden bugs
revealed by the commit 22fca1f2c ("BUG/MEDIUM: filters: Forward all filtered
data at the end of http filtering").

The first one, the worst of both, happens at the end of http filtering when
at least one data filtered is registered on the channel. We call the
http_end() callback function on the filters, when defined, to finish the
http filtering. But it is performed for all filters. Before the commit
22fca1f2c, the only risk was to call the http_end() callback function
unexpectedly on a filter. Now, we may have an overflow on the offset
variable, used at the end to forward all filtered data. Of course, from the
moment we forward an arbitrary huge amount of data, all kinds of bad things
may happen. So offset computation is performed for all filters and
http_end() callback function is called only for data filters.

The other one happens when a data filter alter the data of a channel, it
must update the offsets of all previous filters. But the offset of non-data
filters must be up to date, otherwise, here too we may have an integer
overflow.

Another way to fix these bugs is to always ignore non-data filters from the
offsets computation. But this patch is safer and probably easier to
maintain.

This patch must be backported in all versions where the above commit is. So
as far as 2.0.
2020-11-24 14:17:32 +01:00
Maciej Zdeb
6dee9969b9 BUG/MEDIUM: http_act: Restore init of log-format list
Restore init of log-format list in parse_http_del_header which was
accidently deleted by commit ebdd4c55da
(implementation of different header matching methods for
http-request/response del-header).

This is related to GitHub issue #909
2020-11-24 10:33:46 +01:00
Ilya Shipitsin
d9a16dc0f2 BUILD: SSL: add BoringSSL guarding to "RAND_keep_random_devices_open"
"RAND_keep_random_devices_open" is OpenSSL specific, does not present
in other OpenSSL variants like LibreSSL or BoringSSL. BoringSSL recently
"updated" its internal openssl version to 1.1.1, we temporarily set it
back to 1.1.0, as we are going to remove that hack, let us add proper
guarding.
2020-11-24 09:54:44 +01:00
Julien Pivotto
2de240a676 MINOR: stream: Add level 7 retries on http error 401, 403
Level-7 retries are only possible with a restricted number of HTTP
return codes. While it is usually not safe to retry on 401 and 403, I
came up with an authentication backend which was not synchronizing
authentication of users. While not perfect, being allowed to also retry
on those return codes is really helpful and acts as a hotfix until we
can fix the backend.

Signed-off-by: Julien Pivotto <roidelapluie@inuits.eu>
2020-11-23 09:33:14 +01:00
Tim Duesterhus
c8d19702f4 BUILD: Show the value of DEBUG= in haproxy -vv
Previously this was not visible after building.
2020-11-21 18:27:33 +01:00
Maciej Zdeb
ebdd4c55da MINOR: http_act: Add -m flag for del-header name matching method
This patch adds -m flag which allows to specify header name
matching method when deleting headers from http request/response.
Currently beg, end, sub, str and reg are supported.

This is related to GitHub issue #909
2020-11-21 15:54:30 +01:00
Maciej Zdeb
302b9f8d7a BUG/MINOR: http_htx: Fix searching headers by substring
Function __http_find_header is used to search headers by name using specified
matching method. Matching by substring returned unexpected results due to wrong
length of substring supplied to strnistr function.

Fixed also the boolean condition by inverting it, as we're interested in
headers that contains the substring.

This patch should be backported as far as 2.2
2020-11-21 15:54:26 +01:00
Willy Tarreau
3aab17bd56 BUG/MAJOR: connection: reset conn->owner when detaching from session list
Baptiste reported a new crash affecting 2.3 which can be triggered
when using H2 on the backend, with http-reuse always and with a tens
of clients doing close only. There are a few combined cases which cause
this to happen, but each time the issue is the same, an already freed
session is dereferenced in session_unown_conn().

Two cases were identified to cause this:
  - a connection referencing a session as its owner, which is detached
    from the session's list and is destroyed after this session ends.
    The test on conn->owner before calling session_unown_conn() is not
    sufficent as the pointer is not null but is not valid anymore.

  - a connection that never goes idle and that gets killed form the
    mux, where session_free() is called first, then conn_free() calls
    session_unown_conn() which scans the just freed session for older
    connections. This one is only triggered with DEBUG_UAF

The reason for this session to be present here is that it's needed during
the connection setup, to be passed to conn_install_mux_be() to mux->init()
as the owning session, but it's never deleted aftrewards. Furthermore, even
conn_session_free() doesn't delete this pointer after freeing the session
that lies there. Both do definitely result in a use-after-free that's more
easily triggered under DEBUG_UAF.

This patch makes sure that the owner is always deleted after detaching
or killing the session. However it is currently not possible to clear
the owner right after a synchronous init because the proxy protocol
apparently needs it (a reg test checks this), and if we leave it past
the connection setup with the session not attached anywhere, it's hard
to catch the right moment to detach it. This means that the session may
remain in conn->owner as long as the connection has never been added to
nor removed from the session's idle list. Given that this patch needs to
remain simple enough to be backported, instead it adds a workaround in
session_unown_conn() to detect that the element is already not attached
anywhere.

This fix absolutely requires previous patch "CLEANUP: connection: do not
use conn->owner when the session is known" otherwise the situation will
be even worse, as some places used to rely on conn->owner instead of the
session.

The fix could theorically be backported as far as 1.8. However, the code
in this area has significantly changed along versions and there are more
risks of breaking working stuff than fixing real issues there. The issue
was really woken up in two steps during 2.3-dev when slightly reworking
the idle conns with commit 08016ab82 ("MEDIUM: connection: Add private
connections synchronously in session server list") and when adding
support for storing used H2 connections in the session and adding the
necessary call to session_unown_conn() in the muxes. But the same test
managed to crash 2.2 when built in DEBUG_UAF and patched like this,
proving that we used to already leave dangling pointers behind us:

|  diff --git a/include/haproxy/connection.h b/include/haproxy/connection.h
|  index f8f235c1a..dd30b5f80 100644
|  --- a/include/haproxy/connection.h
|  +++ b/include/haproxy/connection.h
|  @@ -458,6 +458,10 @@ static inline void conn_free(struct connection *conn)
|                          sess->idle_conns--;
|                  session_unown_conn(sess, conn);
|          }
|  +       else {
|  +               struct session *sess = conn->owner;
|  +               BUG_ON(sess && sess->origin != &conn->obj_type);
|  +       }
|
|          sockaddr_free(&conn->src);
|          sockaddr_free(&conn->dst);

It's uncertain whether an existing code path there can lead to dereferencing
conn->owner when it's bad, though certain suspicious memory corruption bugs
make one think it's a likely candidate. The patch should not be hard to
adapt there.

Backports to 2.1 and older are left to the appreciation of the person
doing the backport.

A reproducer consists in this:

  global
    nbthread 1

  listen l
    bind :9000
    mode http
    http-reuse always
    server s 127.0.0.1:8999 proto h2

  frontend f
    bind :8999 proto h2
    mode http
    http-request return status 200

Then this will make it crash within 2-3 seconds:

  $ h1load -e -r 1 -c 10 http://0:9000/

If it does not, it might be that DEBUG_UAF was not used (it's harder then)
and it might be useful to restart.
2020-11-21 15:29:22 +01:00
Willy Tarreau
38b4d2eb22 CLEANUP: connection: do not use conn->owner when the session is known
At a few places we used to rely on conn->owner to retrieve the session
while the session is already known. This is not correct because at some
of these points the reason the connection's owner was still the session
(instead of NULL) is a mistake. At one place a comparison is even made
between the session and conn->owner assuming it's valid without checking
if it's NULL. Let's clean this up to use the session all the time.

Note that this will be needed for a forthcoming fix and will have to be
backported.
2020-11-21 15:29:22 +01:00
Ilya Shipitsin
f34ed0b74c BUILD: SSL: guard TLS13 ciphersuites with HAVE_SSL_CTX_SET_CIPHERSUITES
HAVE_SSL_CTX_SET_CIPHERSUITES is newly defined macro set in openssl-compat.h,
which helps to identify ssl libs (currently OpenSSL-1.1.1 only) that supports
TLS13 cipersuites manipulation on TLS13 context
2020-11-21 11:04:36 +01:00
William Lallemand
77e1c6fb0a BUG/MEDIUM: ssl/crt-list: fix error when no file found
When a file from a crt-list was not found, this one was ignored silently
letting HAProxy starts without it.

This bug was introduced by 47da821 ("MEDIUM: ssl: emulates the
multi-cert bundles in the crtlist").

This commit adds a found variable which is checked once we tried every
bundle combination so we can exits with an error if none were found.

Must be backported in 2.3.
2020-11-20 18:38:56 +01:00
William Lallemand
7340457158 BUG/MINOR: ssl/crt-list: load bundle in crt-list only if activated
Don't try to load a bundle from a crt-list if the bundle support was
disabled with ssl-load-extra-files.

Must be backported to 2.3.
2020-11-20 18:38:56 +01:00
William Lallemand
06ce84a100 BUG/MEDIUM: ssl: error when no certificate are found
When a non-existing file was specified in the configuration, haproxy
does not exits with an error which is not normal.

This bug was introduced by dfa93be ("MEDIUM: ssl: emulate multi-cert
bundles loading in standard loading") which does nothing if the stat
failed.

This patch introduce a "found" variable which is checked at the end of
the function so we exit with an error if no find were found.

Must be backported to 2.3.
2020-11-20 18:38:56 +01:00
William Lallemand
86c2dd60f1 BUG/MEDIUM: ssl/crt-list: bundle support broken in crt-list
In issue #970 it was reported that the bundle loading does not work
anymore with crt-list.

This bug was introduced by 47da821 ("MEDIUM: ssl: emulates the
multi-cert bundles in the crtlist") which incorrectly uses "path"
instead of "crt_path" in the name resolution.

Must be backported to 2.3.
2020-11-20 18:38:51 +01:00
Christopher Faulet
aab1b67383 BUG/MEDIUM: http-ana: Don't eval http-after-response ruleset on empty messages
It is not possible on response comming from a server, but an errorfile may be
empty. In this case, the http-after-response ruleset must not be evaluated
because it is totally unexpected to manipulate headers on an empty HTX message.

This patch must be backported everywhere the http-after-response rules are
supported, i.e as far as 2.2.
2020-11-20 09:43:31 +01:00
Ilya Shipitsin
bdec3ba796 BUILD: ssl: use SSL_MODE_ASYNC macro instead of OPENSSL_VERSION 2020-11-19 19:59:32 +01:00
William Lallemand
f69cd68737 BUG/MINOR: ssl: segv on startup when AKID but no keyid
In bug #959 it was reported that haproxy segfault on startup when trying
to load a certifcate which use the X509v3 AKID extension but without the
keyid field.

This field is not mandatory and could be replaced by the serial or the
DirName.

For example:

   X509v3 extensions:
       X509v3 Basic Constraints:
           CA:FALSE
       X509v3 Subject Key Identifier:
           42:7D:5F:6C:3E:0D:B7:2C:FD:6A:8A:32:C6:C6:B9:90:05:D1:B2:9B
       X509v3 Authority Key Identifier:
           DirName:/O=HAProxy Technologies/CN=HAProxy Test Intermediate CA
           serial:F2:AB:C1:41:9F:AB:45:8E:86:23:AD:C5:54:ED:DF:FA

This bug was introduced by 70df7b ("MINOR: ssl: add "issuers-chain-path" directive").

This patch must be backported as far as 2.2.
2020-11-19 16:24:13 +01:00
William Dauchy
f63704488e MEDIUM: cli/ssl: configure ssl on server at runtime
in the context of a progressive backend migration, we want to be able to
activate SSL on outgoing connections to the server at runtime without
reloading.
This patch adds a `set server ssl` command; in order to allow that:

- add `srv_use_ssl` to `show servers state` command for compatibility,
  also update associated parsing
- when using default-server ssl setting, and `no-ssl` on server line,
  init SSL ctx without activating it
- when triggering ssl API, de/activate SSL connections as requested
- clean ongoing connections as it is done for addr/port changes, without
  checking prior server state

example config:

backend be_foo
  default-server ssl
  server srv0 127.0.0.1:6011 weight 1 no-ssl

show servers state:

  5 be_foo 1 srv0 127.0.0.1 2 0 1 1 15 1 0 4 0 0 0 0 - 6011 - -1

where srv0 can switch to ssl later during the runtime:

  set server be_foo/srv0 ssl on

  5 be_foo 1 srv0 127.0.0.1 2 0 1 1 15 1 0 4 0 0 0 0 - 6011 - 1

Also update existing tests and create a new one.

Signed-off-by: William Dauchy <wdauchy@gmail.com>
2020-11-18 17:22:28 +01:00
William Dauchy
fc52f524b0 MINOR: ssl: create common ssl_ctx init
a common init for ssl_ctx will be later usable in other functions in
order to support hot enable of ssl during runtime.

Signed-off-by: William Dauchy <wdauchy@gmail.com>
2020-11-18 17:22:28 +01:00
Amaury Denoyelle
034c162b9b MEDIUM: stats: add counters for failed handshake
Report on ssl stats the total number of handshakes terminated in a
failure.
2020-11-18 16:10:42 +01:00
Amaury Denoyelle
f70b7db825 MINOR: ssl: remove client hello counters
Remove the ssl client hello received counter. This counter is not
meaningful and was only implemented on the fronted.
2020-11-18 16:10:42 +01:00
Christopher Faulet
47d9a4e870 MINOR: flt-trace: Use a bitfield for the trace options
Instead of using a integer for each option, we now use a bitfield. Each option
is represented as a flag now.
2020-11-17 11:34:36 +01:00
Christopher Faulet
96a577acae MINOR: flt-trace: Add an option to inhibits trace messages
The 'quiet' option may be set to inibits the trace messages. The trace filter is
a bit verbose. This option may be used to not display the messages.
2020-11-17 11:34:36 +01:00
Christopher Faulet
c41d8bd65a CLEANUP: flt-trace: Remove unused random-parsing option
This option was only used by the legacy HTTP mode. In HTX, it is not used. So it
can be removed.
2020-11-17 11:34:30 +01:00
Christopher Faulet
63c69a9b4e BUG/MINOR: http-ana: Don't wait for the body of CONNECT requests
CONNECT requests are bodyless messages but with no EOM blocks. Thus, conditions
to stop waiting for the message payload are not suited to this kind of
messages. Indeed, the message finishes on an EOH block. But the tunnel mode at
the stream level is only set in HTTP_XFER_BODY analyser. So, the stream is
blocked, waiting for a body that does not exist till a timeout expires.

To fix this bug, we just stop waiting for a body for CONNECT requests. Another
solution is to rely on HTX_SL_F_BODYLESS/HTTP_MSGF_BODYLESS flags. But this one
is less intrusive.

This message must be backported as far as 2.0. For the 2.0, only the HTX part
must be fixed.
2020-11-17 10:03:12 +01:00
Christopher Faulet
22fca1f2c8 BUG/MEDIUM: filters: Forward all filtered data at the end of http filtering
When http filtering ends, if there are some filtered data not forwarded yet, we
forward them, in flt_http_end(). Most of time, this doesn't happen, except when
a tunnel is established using a CONNECT. In this case, there is not EOM on the
request and there is no body. Thus the headers are never forwarded, blocking the
stream.

This patch must be backported as far as 2.0. Prior versions don't suffer of this
bug because there is no HTX support. On the 2.0, the change is only applicable
on HTX streams. A special test must be performed to make sure.
2020-11-17 09:59:35 +01:00
Eric Salama
9139ec34ed MINOR: cfgparse: tighten the scope of newnameserver variable, free it on error.
This should fix issue GH #931.

Also remove a misleading comment.

This commit can be backported as far as 1.9
2020-11-13 16:26:10 +01:00
Christopher Faulet
fc633b6eff CLEANUP: config: Return ERR_NONE from config callbacks instead of 0
Return ERR_NONE instead of 0 on success for all config callbacks that should
return ERR_* codes. There is no change because ERR_NONE is a macro equals to
0. But this makes the return value more explicit.
2020-11-13 16:26:10 +01:00
Christopher Faulet
5214099233 MINOR: config/mux-h2: Return ERR_ flags from init_h2() instead of a status
post-check function callbacks must return ERR_* flags. Thus, init_h2() is fixed
to return ERR_NONE on success or (ERR_ALERT|ERR_FATAL) on error.

This patch may be backported as far as 2.2.
2020-11-13 16:26:10 +01:00
Christopher Faulet
83fefbcdff MINOR: init: Fix the prototype for per-thread free callbacks
Functions registered to release memory per-thread have no return value. But the
registering function and the function pointer in per_thread_free_fct structure
specify it should return an integer. This patch fixes it.

This patch may be backported as far as 2.0.
2020-11-13 16:26:10 +01:00
Christopher Faulet
c751b4508d BUG/MINOR: tcpcheck: Don't warn on unused rules if check option is after
When tcp-check or http-check rules are used, if the corresponding check option
(option tcp-check and option httpchk) is declared after the ruleset, a warning
is emitted about an unused check ruleset while there is no problem in reality.

This patch must be backported as far as 2.2.
2020-11-13 16:26:10 +01:00
Christopher Faulet
c7ba91039a MINOR: spoe: Don't close connection in sync mode on processing timeout
In sync mode, if an applet receives a ack while the processing delay has already
expired, there is not frame waiting for this ack. But there is no reason to
close the connection in this case. The ack may be ignored and the connection may
be reused to process another frame. The only reason to trigger an error and
close the connection is when the wrong ack is received while there is still a
frame waiting for its ack. In sync mode, this should never happen.

This patch may be backported in all versions supporting the SPOE.
2020-11-13 16:26:10 +01:00
Christopher Faulet
cf181c76e3 BUG/MAJOR: spoe: Be sure to remove all references on a released spoe applet
When a SPOE applet is used to send a frame, a reference on this applet is saved
in the spoe context of the offladed stream. But, if the applet is released
before receving the corresponding ack, we must be sure to remove this
reference. This was performed for fragmented frames only. But it must also be
performed for a spoe contexts in the applet waiting_queue and in the thread
waiting_queue (used in async mode).

This bug leads to a memory corruption when an offloaded stream try to update the
state of a released applet because it still have a reference on it. There are
many ways to trigger this bug. The easiest is probably during reloads. On the
old process, all applets are woken up to be released ASAP.

Many thanks to Maciej Zdeb to report the bug and to work on it for 2
months. Without his help, it would have been much more difficult to fix the
bug. It is always a huge pleasure to see how some users are enthousiast and
helpful. Thanks again Maciej !

This patch must be backported to all versions where the spoe is supported (>=
1.7).
2020-11-13 16:26:10 +01:00
Christopher Faulet
3005d28eb8 BUG/MINOR: http-htx: Handle warnings when parsing http-error and http-errors
First of all, this patch is tagged as a bug. But in fact, it only fixes a bug in
the 2.2. On the 2.3 and above, it only add the ability to display warnings, when
an http-error directive is parsed from a proxy section and when an errorfile
directive is parsed from a http-errors section.

But on the 2.2, it make sure to display the warning emitted on a content-length
mismatch when an errorfile is parsed. The following is only applicable to the
2.2.

commit "BUG/MINOR: http-htx: Just warn if payload of an errorfile doesn't match
the C-L" (which is only present in 2.2, 2.1 and 2.0 trees, i.e see commit
7bf3d81d3cf4b9f4587 in 2.2 tree), is changing the behavior of `http_str_to_htx`
function. It may now emit warnings. And, it is the caller responsibility to
display it.

But the warning is missing when an 'http-error' directive is parsed from
a proxy section. It is also missing when an 'errorfile' directive is
parsed from a http-errors section.

This bug only exists on the 2.2. On earlier versions, these directives
are not supported and on later ones, an error is triggered instead of a
warning.

Thanks to William Dauchy that spotted the bug.

This patch must be backported as far as 2.2.
2020-11-13 16:26:10 +01:00
Amaury Denoyelle
90eb93f792 MINOR: check: report error on incompatible connect proto
Report an error when using an explicit proto for a connect rule with
non-compatible mode in regards with the selected check type (tcp-check
vs http-check).
2020-11-13 16:26:10 +01:00
Amaury Denoyelle
7c14890183 MINOR: check: report error on incompatible proto
If the check mux has been explicitly defined but is incompatible with
the selected check type (tcp-check vs http-check), report a warning and
prevent haproxy startup.
2020-11-13 16:26:10 +01:00
Amaury Denoyelle
0519bd4d04 BUG/MEDIUM: check: reuse srv proto only if using same mode
Only reuse the mux from server if the check is using the same mode.
For example, this prevents a tcp-check on a h2 server to select the h2
multiplexer instead of passthrough.

This bug was introduced by the following commit :
BUG/MEDIUM: checks: Use the mux protocol specified on the server line
It must be backported up to 2.2.

Fixes github issue #945.
2020-11-13 16:26:10 +01:00
Christopher Faulet
97fc8da264 BUG/MINOR: http-fetch: Fix calls w/o parentheses of the cookie sample fetches
req.cook, req.cook_val, req.cook_cnt and and their response counterparts may be
called without cookie name. In this case, empty parentheses may be used, or no
parentheses at all. In both, the result must be the same. But only the first one
works. The second one always returns a failure. This patch fixes this bug.

Note that on old versions (< 2.2), both cases fail.

This patch must be backported in all stable versions.
2020-11-13 16:26:10 +01:00
Maciej Zdeb
dea7c209f8 BUG/MINOR: http-fetch: Extract cookie value even when no cookie name
HTTP sample fetches dealing with the cookies (req/res.cook,
req/res.cook_val and req/res.cook_cnt) must be prepared to be called
without cookie name. For the first two, the first cookie value is
returned, regardless its name. For the last one, all cookies are counted.

To do so, http_extract_cookie_value() may now be called with no cookie
name (cookie_name_l set to 0). In this case, the matching on the cookie
name is ignored and the first value found is returned.

Note this patch also fixes matching on cookie values in ACLs.

This should be backported in all stable versions.
2020-11-13 16:26:10 +01:00
Willy Tarreau
1dfd4f106f BUG/MEDIUM: peers: fix decoding of multi-byte length in stick-table messages
There is a bug in peer_recv_msg() due to an incorrect cast when trying
to decode the varint length of a stick-table message, causing lengths
comprised between 128 and 255 to consume one extra byte, ending in
protocol errors.  The root cause of this is that peer_recv_msg() tries
hard to reimplement all the parsing and control that is already done in
intdecode() just to measure the length before calling it. And it got it
wrong.

Let's just get rid of this unneeded code duplication and solely rely on
intdecode() instead. The bug was introduced in 2.0 as part of a cleanup
pass on this code with commit 95203f218 ("MINOR: peers: Move high level
receive code to reduce the size of I/O handler."), so this patch must
be backported to 2.0.

Thanks to Yves Lafon for reporting the problem.
2020-11-13 15:21:50 +01:00
Frdric Lcaille
ea875e62e6 BUG/MINOR: peers: Missing TX cache entries reset.
The TX part of a cache for a dictionary is made of an reserved array of ebtree nodes
which are pointers to dictionary entries. So when we flush the TX part of such a
cache, we must not only remove these nodes to dictionary entries from their ebtree.
We must also reset their values. Furthermore, the LRU key and the last lookup
result must also be reset.
2020-11-13 06:04:18 +01:00
Frdric Lcaille
f9e51beec1 BUG/MINOR: peers: Do not ignore a protocol error for dictionary entries.
If we could not decode the ID of a dictionary entry from a peer update message,
we must inform the remote peer about such an error as this is done for
any other decoding error.
2020-11-13 06:04:08 +01:00
Frdric Lcaille
d865935f32 MINOR: peers: Add traces to peer_treat_updatemsg().
Add minimalistic traces for peers with only one event to diagnose potential
issues when decode peer update messages.
2020-11-12 17:38:49 +01:00
Amaury Denoyelle
7f8f6cb926 BUG/MEDIUM: stats: prevent crash if counters not alloc with dummy one
Define a per-thread counters allocated with the greatest size of any
stat module counters. This variable is named trash_counters.

When using a proxy without allocated counters, return the trash counters
from EXTRA_COUNTERS_GET instead of a dangling pointer to prevent
segfault.

This is useful for all the proxies used internally and not
belonging to the global proxy list. As these objects does not appears on
the stat report, it does not matter to use the dummy counters.

For this fix to be functional, the extra counters are explicitly
initialized to NULL on proxy/server/listener init functions.

Most notably, the crash has already been detected with the following
vtc:
- reg-tests/lua/txn_get_priv.vtc
- reg-tests/peers/tls_basic_sync.vtc
- reg-tests/peers/tls_basic_sync_wo_stkt_backend.vtc
There is probably other parts that may be impacted (SPOE for example).

This bug was introduced in the current release and do not need to be
backported. The faulty commits are
"MINOR: ssl: count client hello for stats" and
"MINOR: ssl: add counters for ssl sessions".
2020-11-12 15:16:05 +01:00
Amaury Denoyelle
a2a6899bee BUG/MINOR: stats: free dynamically stats fields/lines on shutdown
Register a new function on POST DEINIT to free stats fields/lines for
each domain.

This patch does not fix a critical bug but may be backported to 2.3.
2020-11-12 15:16:05 +01:00
Remi Tricot-Le Breton
cc9bf2e5fe MEDIUM: cache: Change caching conditions
Do not cache responses that do not have an explicit expiration time
(s-maxage or max-age Cache-Control directives or Expires header) or a
validator (ETag or Last-Modified headers) anymore, as suggested in
RFC 7234#3.
The TX_FLAG_IGNORE flag is used instead of the TX_FLAG_CACHEABLE so as
not to change the behavior of the checkcache option.
2020-11-12 11:22:05 +01:00
Thierry Fournier
91dc0c0d8f BUG/MINOR: lua: set buffer size during map lookups
This size is used by some pattern matching to determine if there
is sufficient room in the buffer to add final \0 if necessary.
If the size is not set, the conditions use uninitialized value.

Note: it seems this bug can't cause a crash.

Should be backported until 2.2 (at least)
2020-11-11 10:43:21 +01:00
Thierry Fournier
a68affeaa9 BUG/MINOR: pattern: a sample marked as const could be written
The functions add final 0 to string if the final 0 is not set,
but don't check the flag CONST. This patch duplicates the strings
if the final zero is not set and the string is CONST.

Should be backported until 2.2 (at least)
2020-11-11 10:43:15 +01:00
William Lallemand
50c03aac04 BUG/MEDIUM: ssl/crt-list: correctly insert crt-list line if crt already loaded
In issue #940, it was reported that the crt-list does not work correctly
anymore. Indeed when inserting a crt-list line which use a certificate
previously seen in the crt-list, this one won't be inserted in the SNI
list and will be silently ignored.

This bug was introduced by commit  47da821 "MEDIUM: ssl: emulates the
multi-cert bundles in the crtlist".

This patch also includes a reg-test which tests this issue.

This bugfix must be backported in 2.3.
2020-11-06 16:39:39 +01:00
Willy Tarreau
431a12cafe BUILD: http-htx: fix build warning regarding long type in printf
Commit a66adf41e ("MINOR: http-htx: Add understandable errors for the
errorfiles parsing") added a warning when loading malformed error files,
but this warning may trigger another build warning due to the %lu format
used. Let's simply cast it for output since it's just used for end user
output.

This must be backported to 2.0 like the commit above.
2020-11-06 14:24:02 +01:00
Willy Tarreau
4299528390 BUILD: ssl: silence build warning on uninitialised counters
Since commit d0447a7c3 ("MINOR: ssl: add counters for ssl sessions"),
gcc 9+ complains about this:

  CC      src/ssl_sock.o
src/ssl_sock.c: In function 'ssl_sock_io_cb':
src/ssl_sock.c:5416:3: warning: 'counters_px' may be used uninitialized in this function [-Wmaybe-uninitialized]
 5416 |   ++counters_px->reused_sess;
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~
src/ssl_sock.c:5133:23: note: 'counters_px' was declared here
 5133 |  struct ssl_counters *counters, *counters_px;
      |                                  ^~~~~~~~~~~

Either a listener or a server are expected there, so ther counters are
always initialized and the compiler cannot know this. Let's preset
them and test before updating the counter, we're not in a hot path
here.

No backport is needed.
2020-11-06 13:22:44 +01:00
Willy Tarreau
f5fe70620c MINOR: server: remove idle lock in srv_cleanup_connections
This function used to grab the idle lock when scanning the threads for
idle connections, but it doesn't need it since the lock only protects
the tree. Let's remove it.
2020-11-06 13:22:44 +01:00
Amaury Denoyelle
d0447a7c3e MINOR: ssl: add counters for ssl sessions
Add counters for newly established and resumed sessions.
2020-11-06 12:05:17 +01:00
Amaury Denoyelle
fbc3377cd4 MINOR: ssl: count client hello for stats
Add a counter for ssl client_hello received on frontends.
2020-11-06 12:05:17 +01:00
Amaury Denoyelle
9963fa74d2 MINOR: ssl: instantiate stats module
This module is responsible for providing statistics for ssl. It allocates
counters for frontend/backend/listener/server objects.
2020-11-06 12:05:17 +01:00
Christopher Faulet
a66adf41ea MINOR: http-htx: Add understandable errors for the errorfiles parsing
No details are provided when an error occurs during the parsing of an errorfile,
Thus it is a bit hard to diagnose where the problem is. Now, when it happens, an
understandable error message is reported.

This patch is not a bug fix in itself. But it will be required to change an
fatal error into a warning in last stable releases. Thus it must be backported
as far as 2.0.
2020-11-06 09:13:58 +01:00
Willy Tarreau
6d27a92b83 BUG/MINOR: ssl: don't report 1024 bits DH param load error when it's higher
The default dh_param value is 2048 and it's preset to zero unless explicitly
set, so we must not report a warning about DH param not being loadble in 1024
bits when we're going to use 2048. Thanks to Dinko for reporting this.

This should be backported to 2.2.
2020-11-05 19:40:14 +01:00
Jerome Magnin
eff2e0a958 CLEANUP: cfgparse: remove duplicate registration for transparent build options
Since commit 37bafdcbb ("MINOR: sock_inet: move the IPv4/v6 transparent mode code
to sock_inet"), build options for transparent proxying are registered twice.
This patch removes the older one.
2020-11-05 19:27:16 +01:00
Willy Tarreau
38d41996c1 MEDIUM: pattern: turn the pattern chaining to single-linked list
It does not require heavy deletion from the expr anymore, so we can now
turn this to a single-linked list since most of the time we want to delete
all instances of a given pattern from the head. By doing so we save 32 bytes
of memory per pattern. The pat_unlink_from_head() function was adjusted
accordingly.
2020-11-05 19:27:09 +01:00
Willy Tarreau
867a8a5a10 MINOR: pattern: prepare removal of a pattern from the list head
Instead of using LIST_DEL() on the pattern itself inside an expression,
we look it up from its head. The goal is to get rid of the double-linked
list while this usage remains exclusively for freeing on startup error!
2020-11-05 19:27:09 +01:00
Willy Tarreau
2817472bb0 MINOR: pattern: during reload, delete elements frem the ref, not the expression
Instead of scanning all elements from the expression and using the
slow delete path there, let's use the faster way which involves
pat_delete_gen() while the elements are detached from ther reference.
2020-11-05 19:27:09 +01:00
Willy Tarreau
ae83e63b48 MEDIUM: pattern: make pat_ref_prune() rely on pat_ref_purge_older()
When purging all of a reference, it's much more efficient to scan the
reference patterns from the reference head and delete all derivative
patterns than to scan the expressions. The only thing is that we need
to proceed both for the current and next generations, in case there is
a huge gap between the two. With this, purging 20M IP addresses in small
batches of 100 takes roughly 3 seconds.
2020-11-05 19:27:09 +01:00
Willy Tarreau
94b9abe200 MINOR: pattern: add pat_ref_purge_older() to purge old entries
This function will be usable to purge at most a specified number of old
entries from a reference. Entries are declared old if their generation
number is in the past compared to the one passed in argument. This will
ease removal of early entries when new ones have been appended.

We also call malloc_trim() when available, at the end of the series,
because this is one place where there is a lot of memory to save. Reloads
of 1M IP addresses used in an ACL made the process grow up to 1.7 GB RSS
after 10 reloads and roughly stabilize there without this call, versus
only 260 MB when the call is present. Sadly there is no direct equivalent
for jemalloc, which stabilizes around 800MB-1GB.
2020-11-05 19:27:09 +01:00
Willy Tarreau
1a6857b9c1 MINOR: pattern: implement pat_ref_load() to load a pattern at a given generation
pat_ref_load() basically combines pat_ref_append() and pat_ref_commit().
It's very similar to pat_ref_add() except that it also allows to set the
generation ID and the line number. pat_ref_add() was modified to directly
rely on it to avoid code duplication. Note that a previous declaration
of pat_ref_load() was removed as it was just a leftover of an earlier
incarnation of something possibly similar, so no existing functionality
was changed here.
2020-11-05 19:27:09 +01:00
Willy Tarreau
0439e5eeb4 MINOR: pattern: add pat_ref_commit() to commit a previously inserted element
This function will be used after a successful pat_ref_append() to propagate
the pattern to all use places (including parsing and indexing). On failure,
it will entirely roll back all insertions and free the pattern itself. It
also preserves the generation number so that it is convenient for use in
association with pat_ref_append(). pat_ref_add() was modified to rely on
it instead of open-coding the insertion and roll-back.
2020-11-05 19:27:09 +01:00
Willy Tarreau
c93da6950e MEDIUM: pattern: only match patterns that match the current generation
Instead of matching any pattern found in the tree, only match those
matching the current generation of entries. This will make sure that
reloads are atomic, regardless of the time they take to complete, and
that newly added data are not matched until the whole reference is
committed. For consistency we proceed the same way on "show map" and
"show acl".

This will have no impact for now since generations are not used.
2020-11-05 19:27:09 +01:00
Willy Tarreau
29947745b5 MINOR: pattern: store a generation number in the reference patterns
Right now it's not possible to perform a safe reload because we don't
know what patterns were recently added or were already present. This
patch adds a generation counter to the reference patterns so that it
is possible to know what generation of the reference they were loaded
with. A reference now has two generations, the current one, used for
all additions, and the next one, allocated to those wishing to update
the contents. The generation wraps at 2^32 so comparisons must be made
relative to the current position.

The idea will be that upon full reload, the caller will first get a new
generation ID, will insert all new patterns using it, will then switch
the current ID to the new one, and will delete all entries older than
the current ID. This has the benefit of supporting chunked updates that
remain consistent and that won't block the whole process for ages like
pat_ref_reload() currently does.
2020-11-05 19:27:09 +01:00
Willy Tarreau
1fd52f70e5 MINOR: pattern: introduce pat_ref_delete_by_ptr() to delete a valid reference
Till now the only way to remove a known reference was via
pat_ref_delete_by_id() which scans the whole list to find a matching pointer.
Let's add pat_ref_delete_by_ptr() which takes a valid pointer. It can be
called by the function above after the pointer is found, and can also be
used to roll back a failed insertion much more efficiently.
2020-11-05 19:27:09 +01:00
Willy Tarreau
a98b2882ac CLEANUP: pattern: remove pat_delete_fcts[] and pattern_head->delete()
These ones are not used anymore, so let's remove them to remove a bit
of the complexity. The ACL keyword's delete() function could be removed
as well, though most keyword declarations are positional and we have a
high risk of introducing a mistake here, so let's not touch the ACL part.
2020-11-05 19:27:09 +01:00
Willy Tarreau
b35aa9b256 CLEANUP: acl: don't reference the generic pattern deletion function anymore
A few ACL keyword used to reference pat_delete_gen() as the deletion
function but this is not needed since it's the default one now. Let's
just remove this reference.
2020-11-05 19:27:09 +01:00
Willy Tarreau
e828d8f0e8 MINOR: pattern: perform a single call to pat_delete_gen() under the expression
When we're removing an element under the expression lock, we don't need
anymore to run over all ->delete() functions via the expressions, since
we know that the single function does it fine now. Note that at this
point, pattern->delete() is not used at all through out the code anymore.
2020-11-05 19:27:09 +01:00
Willy Tarreau
f1c0892aa6 MINOR: pattern: remerge the list and tree deletion functions
pat_del_tree_gen() was already chained onto pat_del_list_gen() to deal
with remaining cases, so let's complete the merge and have a generic
pattern deletion function acting on the reference and taking care of
reliably removing all elements.
2020-11-05 19:27:09 +01:00
Willy Tarreau
78777ead32 MEDIUM: pattern: change the pat_del_* functions to delete from the references
This is the next step in speeding up entry removal. Now we don't scan
the whole lists or trees for elements pointing to the target reference,
instead we start from the reference and delete all linked patterns.

This simplifies some delete functions since we don't need anymore to
delete multiple times from an expression since all nodes appear after
the reference element. We can now have one generic list and one generic
tree deletion function.

This required the replacement of pattern_delete() with an open-coded
version since we now need to lock all expressions first before proceeding.
This means there is a high risk of lock inversion here but given that the
expressions are always scanned in the same order from the same head, this
must not happen.

Now deleting first entries is instantaneous, and it's still slow to
delete the last ones when looking up their ID since it still requires
to look them up by a full scan, but it's already way faster than
previously. Typically removing the last 10 IP from a 20M entries ACL
with a full-scan each took less than 2 seconds.

It would be technically possible to make use of indexed entries to
speed up most lookups for removal by value (e.g. IP addresses) but
that's for later.
2020-11-05 19:27:09 +01:00
Willy Tarreau
4bdd0a13d6 MEDIUM: pattern: link all final elements from the reference
There is a data model issue in the current pattern design that makes
pattern deletion extremely expensive: there's no direct way from a
reference to access all indexed occurrences. As such, the only way
to remove all indexed entries corresponding to a reference update
is to scan all expressions's lists and trees to find a link to the
reference. While this was possibly OK when map removal was not
common and most maps were small, this is not conceivable anymore
with GeoIP maps containing 10M+ entries and del-map operations that
are triggered from http-request rulesets.

This patch introduces two list heads from the pattern reference, one
for the objects linked by lists and one for those linked by tree node.
Ideally a single list would be enough but the linked elements are too
much unrelated to be distinguished at the moment, so we'll need two
lists. However for the long term a single-linked list will suffice but
for now it's not possible due to the way elements are removed from
expressions. As such this patch adds 32 bytes of memory usage per
reference plus 16 per indexed entry, but both will be cut in half
later.

The links are not yet used for deletion, this patch only ensures the
list is always consistent.
2020-11-05 19:27:09 +01:00
Willy Tarreau
6d8a68914e MINOR: pattern: make the delete and prune functions more generic
Now we have a single prune() function to act on an expression, and one
delete function for the lists and one for the trees. The presence of a
pointer in the lists is enough to warrant a free, and we rely on the
PAT_SF_REGFREE flag to decide whether to free using free() or regfree().
2020-11-05 19:27:09 +01:00
Willy Tarreau
9b5c8bbc89 MINOR: pattern: new sflag PAT_SF_REGFREE indicates regex_free() is needed
Currently we have no way to know how to delete/prune a pattern in a
generic way. A pattern doesn't contain its own type so we don't know
what function to call. Tree nodes are roughly OK but not lists where
regex are possible. Let's add one new bit for sflags at index time to
indicate that regex_free() will be needed upon deletion. It's not used
for now.
2020-11-05 19:27:08 +01:00
Willy Tarreau
d4164dcd4a CLEANUP: pattern: delete the back refs at once during pat_ref_reload()
It's pointless to delete a backref and relink it to the next entry since
the next entry is going to do the exact same and so on until all of them
are deleted. Let's simply delete backrefs on reload.
2020-11-05 19:27:08 +01:00
Willy Tarreau
3ee0de1b41 MINOR: pattern: move the update revision to the pat_ref, not the expression
It's not possible to uniquely update a single expression without updating
the pattern reference, I don't know why we've put the revision in the
expression back then, given that it in fact provides an update for a
full pattern. Let's move the revision into the reference's head instead.
2020-11-05 19:27:08 +01:00
Willy Tarreau
114d698fde MEDIUM: pattern: call malloc_trim() on pat_ref_reload()
This is one case where we may release large amounts of data at once. Tests
show that without this, after 10 full reloads of an ACL containing  1M IP
addresses, the memory usage grew and stabilized around 1.7 GB of RSS. With
this change, it stays around 260 MB and is stable across reloads.
2020-11-05 19:27:08 +01:00
Willy Tarreau
88366c2926 MEDIUM: pools: call malloc_trim() from pool_gc()
If available it definitely makes sense to call it since it's also
called when stopping to reclaim the maximum possible memory.
2020-11-05 19:27:08 +01:00
Baptiste Assmann
e279ca6bbe MINOR: sample: Add converts to parses MQTT messages
This patch implements a couple of converters to validate and extract data from a
MQTT (Message Queuing Telemetry Transport) message. The validation consists of a
few checks as well as "packet size" validation. The extraction can get any field
from the variable header and the payload.

This is limited to CONNECT and CONNACK packet types only. All other messages are
considered as invalid. It is not a problem for now because only the first packet
on each side can be parsed (CONNECT for the client and CONNACK for the server).

MQTT 3.1.1 and 5.0 are supported.

Reviewed and Fixed by Christopher Faulet <cfaulet@haproxy.com>
2020-11-05 19:27:03 +01:00
Baptiste Assmann
e138dda1e0 MINOR: sample: Add converters to parse FIX messages
This patch implements a couple of converters to validate and extract tag value
from a FIX (Financial Information eXchange) message. The validation consists in
a few checks such as mandatory fields and checksum computation. The extraction
can get any tag value based on a tag string or tag id.

This patch requires the istend() function. Thus it depends on "MINOR: ist: Add
istend() function to return a pointer to the end of the string".

Reviewed and Fixed by Christopher Faulet <cfaulet@haproxy.com>
2020-11-05 19:26:30 +01:00
Ilya Shipitsin
0aa8c29460 BUILD: ssl: use feature macros for detecting ec curves manipulation support
Let us use SSL_CTX_set1_curves_list, defined by OpenSSL, as well as in
openssl-compat when SSL_CTRL_SET_CURVES_LIST is present (BoringSSL),
for feature detection instead of versions.
2020-11-05 15:08:41 +01:00
William Lallemand
99e0bb997f MINOR: mworker/cli: the master CLI use its own applet
Following the patch b4daee ("MINOR: sock: add a check against cross
worker<->master socket activities"), this patch adds a dedicated applet
for the master CLI. It ensures that the CLI connection can't be
used with the master rights in the case of bugs.
2020-11-05 10:28:53 +01:00
Willy Tarreau
21b9ff59b2 BUG/MEDIUM: server: make it possible to kill last idle connections
In issue #933, @jaroslawr provided a report indicating that when using
many threads and many servers, it's very difficult to terminate the last
idle connections on each server. The issue has two causes in fact. The
first one is that during the calculation of the estimate of needed
connections, we round the computation up while in previous round it was
already rounded up, so we end up adding 1 to 1 which once divided by 2
remains 1. The second issue is that servers are not woken up anymore for
purging their connections if they don't have activity. The only reason
that was there to wake them up again was in case insufficient connections
were purged. And even then the purge task itself was not woken up. But
that is not enough for getting rid of the long tail of old connections
nor updating est_need_conns.

This patch makes sure to properly wake up as long as at least one idle
connection remains, and not to round up the needed connections anymore.

Prior to this patch, a test involving many connections which suddenly
stopped would keep many idle connections, now they're effectively halved
every pool-purge-delay.

This needs to be backported to 2.2.
2020-11-05 09:12:20 +01:00
Willy Tarreau
b4daeeb094 MINOR: sock: add a check against cross worker<->master socket activities
Given that the previous issues caused spurious worker socket wakeups in
the master for inherited FDs that couldn't be closed, let's add a strict
test in the I/O callback to make sure that an accept() event is always
caught by the appropriate type of process (master for master listeners,
worker for worker listeners).
2020-11-04 15:05:50 +01:00
Christopher Faulet
fafd1b0a5b CLEANUP: mux-h2: Remove the h1 parser state from the h2 stream
Since the h2 multiplexer no longer relies on the legacy HTTP representation, and
uses exclusively the HTX, the H1 parser state (h1m) is no longer used by the h2
streams. Thus it can be removed.

This patch may be backported as far as 2.1.
2020-11-04 15:02:24 +01:00
Willy Tarreau
a4380b211f MEDIUM: listeners: make use of fd_want_recv_safe() to enable early receivers
We used to refrain from calling fd_want_recv() if fd_updt was not allocated
but it's not the right solution as this does not allow the FD to be set.
Instead, let's use the new fd_want_recv_safe() which will update the FD and
create an update entry only if possible. In addition, the equivalent test
before calling fd_stop_recv() was removed as totally useless since there's
not fd_updt creation in this case.
2020-11-04 14:22:42 +01:00
Willy Tarreau
22ccd5ebaf BUG/MEDIUM: listener: make the master also keep workers' inherited FDs
In commit 374e9af35 ("MEDIUM: listener: let do_unbind_listener() decide
whether to close or not") it didn't appear necessary to have the master
process keep open the workers' inherited FDs. But this is actually
necessary to handle the reload on "bind fd@foo" situations, otherwise
the FD may be reassigned and the new socket cannot be set up, sometimes
causing "socket operation on non-socket" or other types of errors.

William found that this was the cause for the consistent failures of the
abns regtest, which already used to fail very often before this and was
as such marked as broken.

Interestingly I didn't have this issue with my test configs because
the FD number I used was higher and within the range of other listening
sockets. But this means that one of these wouldn't work as expected.

No backport is needed, this was introduced as part of the listeners
rework in 2.3.
2020-11-04 14:22:42 +01:00
Willy Tarreau
59b5da4873 BUG/MEDIUM: listener: never suspend inherited sockets
It is not acceptable to suspend an inherited socket because we'd kill
its listening state, making it possibly unrecoverable for future
processes. The situation which can trigger this is when there is an
abns socket in a config and an inherited FD on another listener. Upon
soft reload, the abns fails to bind, a SIGTTOU is sent to the old
process which suspends everything, including the inherited FD, then
the new process can bind and tell the old one to quit. Except that the
new FD was not set back to the listen state, which is detected by
listener_accept() which can pause it. It's only upon second reload
that the FD works again.

The solution is to refrain from suspending such FDs since we don't own
them. And the next process will get them right anyway from its config.
For now only TCP and UDP face this issue so it's better to address this
on a protocol basis

No backport is needed, this is related to the new listeners in 2.3.
2020-11-04 14:22:42 +01:00
Willy Tarreau
38dba27d4d BUG/MEDIUM: listener: only enable a listening listener if needed
The test on listener->state == LI_LISTEN is not sufficient to decide
if we need to enable a listener. Indeed, there is a very special case
which is the inherited FD shared, which has to reflect the real socket
state even after the previous test, and as such needs to remain in
LI_LISTEN state. In this case we don't want a worker to start the
master's listener nor conversely. Let's add a specific test for this.
2020-11-04 14:22:42 +01:00
Willy Tarreau
dfe79251da BUG/MEDIUM: stick-table: limit the time spent purging old entries
An interesting case was reported with threads and moderately sized
stick-tables. Sometimes the watchdog would trigger during the purge.
It turns out that the stick tables were sized in the 10s of K entries
which is the order of magnitude of the possible number of connections,
and that threads were used over distinct NUMA nodes. While at first
glance nothing looks problematic there, actually there is a risk that
a thread trying to purge the table faces 100% of entries still in use
by a connection with (ts->ref_cnt > 0), and ends up scanning the whole
table, while other threads on the other NUMA node are causing the
cache lines to bounce back and forth and considerably slow down its
progress to the point of possibly spending hundreds of milliseconds
there, multiplied by the number of queued threads all failing on the
same point.

Interestingly, smaller tables would not trigger it because the scan
would be faster, and larger ones would not trigger it because plenty
of entries would be idle!

The most efficient solution is to increase the table size to be large
enough for this never to happen, but this is not reliable. We could
have a parallel list of idle entries but that would significantly
increase the storage and processing cost only to improve a few rare
corner cases.

This patch takes a more pragmatic approach, it considers that it will
not visit more than twice the number of nodes to be deleted, which
means that it accepts to fail up to 50% of the time. Given that very
small batches are programmed each time (1/256 of the table size), this
means the operation will finish quickly (128 times faster than now),
and will reduce the inter-thread contention. If this needs to be
reconsidered, it will probably mean that the batch size needs to be
fixed differently.

This needs to be backported to stable releases which extensively use
threads, typically 2.0.

Kudos to Nenad Merdanovic for figuring the root cause triggering this!
2020-11-03 18:02:42 +01:00
Amaury Denoyelle
e6ee820c07 MINOR: stats: do not display empty stat module title on html
If a stat module is not available on the current proxy scope, do not
display its title on the related html box. This is clearer for the user.
2020-11-03 17:04:22 +01:00
Amaury Denoyelle
e7b891f7d3 MINOR: mux_h2: add stat for total count of connections/streams
Add counters for total number of http2 connections/stream since haproxy
startup. Contrary to open_conn/stream, they are never reset to zero.
2020-11-03 17:04:22 +01:00
Amaury Denoyelle
2ac34d97a6 MINOR: mux_h2: capitalize frame type in stats
http/2 frame type names are capitalized in the rfc, use the same
notation on the stats labels.
2020-11-03 17:04:22 +01:00
Christopher Faulet
743bd6adc8 BUG/MINOR: filters: Skip disabled proxies during startup only
This partially reverts the patch 400829cd2 ("BUG/MEDIUM: filters: Don't try to
init filters for disabled proxies"). Disabled proxies must not be skipped in
flt_deinit() and flt_deinit_all_per_thread() when HAProxy is stopped because,
obvioulsy, at this step, all proxies appear as disabled (or stopped, it is the
same state). It is safe to do so because, during startup, filters declared on
disabled proxies are removed. Thus they don't exist anymore during shutdown.

This patch must be backported in all versions where the patch above is.
2020-11-03 16:51:48 +01:00
Ilya Shipitsin
04a5a440b8 BUILD: ssl: use HAVE_OPENSSL_KEYLOG instead of OpenSSL versions
let us use HAVE_OPENSSL_KEYLOG for feature detection instead
of versions
2020-11-03 14:54:15 +01:00
Christopher Faulet
5a7ca29061 BUG/MEDIUM: mux-pt: Release the tasklet during an HTTP upgrade
When a TCP connection is upgraded to HTTP, the passthrough multiplexer owning
the client connection is detroyed and replaced by an HTTP multiplexer. When it
happens, the connection context is changed (it is in fact the mux itself). Thus,
when the mux-pt is destroyed, the connection is not released. But, only the
connection must be kept. Everything else concerning the mux must be
released. Especially, the tasklet used for I/O subscriptions. In this part,
there was a bug and the tasklet was never released.

This patch should fix the issue #935. It must be backported as far as 2.0.
2020-11-03 10:50:00 +01:00
Christopher Faulet
75bef00538 MINOR: server: Copy configuration file and line for server templates
When servers based on server templates are initialized, the configuration file
and line are now copied. This helps to emit understandable warning and alert
messages.

This patch may be backported if needed, as far as 1.8.
2020-11-03 10:44:38 +01:00
Christopher Faulet
ac1c60fd9c BUG/MINOR: server: Set server without addr but with dns in RMAINT on startup
On startup, if a server has no address but the dns resolutions are configured,
"none" method is added to the default init-addr methods, in addition to "last"
and "libc". Thus on startup, this server is set to RMAINT mode if no address is
found. It is only performed if no other init-addr method is configured.

Setting the RMAINT mode on startup is important to inhibit the health checks.

For instance, following servers will now be set to RMAINT mode on startup :

  server srv nofound.tld:80 check resolvers mydns
  server srv _http._tcp.service.local check resolvers mydns
  server-template srv 1-3 _http._tcp.service.local check resolvers mydns

while followings ones will trigger an error :

  server srv nofound.tld:80 check
  server srv nofound.tld:80 check resolvers mydns init-addr libc
  server srv _http._tcp.service.local check
  server srv _http._tcp.service.local check resolvers mydns init-addr libc
  server-template srv 1-3 _http._tcp.service.local check resolvers mydns init-addr libc

This patch must be backported as far as 1.8.
2020-11-03 10:44:26 +01:00
Christopher Faulet
5e29376efb BUG/MINOR: checks: Report a socket error before any connection attempt
When a health-check fails, if no connection attempt was performed, a socket
error must be reported. But this was only done if the connection was not
allocated. It must also be done if there is no control layer. Otherwise, a
L7TOUT will be reported instead.

It is possible to not having a control layer for a connection if the connection
address family is invalid or not defined.

This patch must be backported to 2.2.
2020-11-03 10:23:00 +01:00
Christopher Faulet
d5bd824b81 BUG/MINOR: proxy/server: Skip per-proxy/server post-check for disabled proxies
per-proxy and per-server post-check callback functions must be skipped for
disabled proxies because most of the configuration validity check is skipped for
these proxies.

This patch must be backported as far as 2.1.
2020-11-03 10:23:00 +01:00
Christopher Faulet
400829cd2c BUG/MEDIUM: filters: Don't try to init filters for disabled proxies
Configuration is parsed for such proxies but not validated. Concretely, it means
check_config_validity() function does almost nothing for such proxies. Thus, we
must be careful to not initialize filters for disabled proxies because the check
callback function is not called. In fact, to be sure to avoid any trouble,
filters for disabled proxies are released.

This patch fixes a segfault at startup if the SPOE is configured for a disabled
proxy. It must be backported as far as 1.7 (maybe with some adaptations).
2020-11-03 10:23:00 +01:00
Ilya Shipitsin
c9dfee43f3 BUILD: ssl: use SSL_CTRL_GET_RAW_CIPHERLIST instead of OpenSSL versions
let us use SSL_CTRL_GET_RAW_CIPHERLIST for feature detection instead
of versions

[wla: SSL_CTRL_GET_RAW_CIPHERLIST was introduced by OpenSSL commit
94a209 along with SSL_CIPHER_find. It was removed in boringSSL.]
Signed-off-by: William Lallemand <wlallemand@haproxy.org>
2020-11-03 09:24:43 +01:00
Willy Tarreau
a5bbaaf9f4 CLEANUP: pattern: fix spelling/grammatical/copy-paste in comments
The code is horrible to work with because most functions are documented
with misleading comments resulting from many spelling and grammatical
mistakes, and plenty of remains of copy-paste mentioning arguments that
do not exist and return values that are never set. Too many hours wasted
writing non-working code because of assumptions resulting from this,
let's fix this once for all now!
2020-10-31 13:14:10 +01:00
Willy Tarreau
8135d9bc0c CLEANUP: pattern: use calloc() rather than malloc for structures
It's particularly difficult to make sure that the various pattern
structures are properly initialized given that they can be allocated
at multiple places and systematically via malloc() instead of calloc(),
thus not even leaving the possibility of default values. Let's adjust
a few of them.
2020-10-31 13:14:10 +01:00
Willy Tarreau
6bedf151e1 MINOR: pattern: export pat_ref_push()
Strangely this one was marked static inline within the file itself.
Let's export it.
2020-10-31 13:13:48 +01:00
Willy Tarreau
6a1740767c MINOR: pattern: make pat_ref_add() rely on pat_ref_append()
Let's remove unneeded code duplication, both are exactly the same.
2020-10-31 13:13:48 +01:00
Willy Tarreau
f4edb72e0a MINOR: pattern: make pat_ref_append() return the newly added element
It's more convenient to return the element than to return just 0 or 1,
as the next thing we'll want to do is to act on this element! In addition
it was using variable arguments instead of consts, causing some reuse
constraints which were also addressed. This doesn't change its use as
a boolean, hence why call places were not modified.
2020-10-31 13:13:48 +01:00
Remi Tricot-Le Breton
8c2db71326 BUG/MINOR: cache: Inverted variables in http_calc_maxage function
The maxage and smaxage variables were inadvertently assigned the
Cache-Control s-maxage and max-age values respectively when it should
have been the other way around.

This can be backported on all branches after 1.8 (included).
2020-10-30 14:29:29 +01:00
Remi Tricot-Le Breton
40ed97b04b BUG/MINOR: cache: Manage multiple values in cache-control header value
If an HTTP request or response had a "Cache-Control" header that had
multiple comma-separated subparts in its value (like "max-age=1,
no-store" for instance), we did not process the values correctly and
only parsed the first one. That made us store some HTTP responses in the
cache when they were explicitely uncacheable.
This patch replaces the way the values are parsed by an http_find_header
loop that manages every sub part of the value independently.

This patch should be backported to 2.2 and 2.1. The bug also exists on
previous versions but since the sources changed, a new commit will have
to be created.

[wla: This patch requires bb4582c ("MINOR: ist: Add a case insensitive
istmatch function"). Backporting for < 2.1 is not a requirement since it
works well enough for most cases, it was a known limitation of the
implementation of non-htx version too]
2020-10-30 13:28:34 +01:00
Remi Tricot-Le Breton
a6476114ec MINOR: cache: Add Expires header value parsing
When no Cache-Control max-age or s-maxage information is present in a
cached response, we need to parse the Expires header value (RFC 7234#5.3).
An invalid Expires date value or a date earlier than the reception date
will make the cache_entry stale upon creation.
For now, the Cache-Control and Expires headers are parsed after the
insertion of the response in the cache so even if the parsing of the
Expires results in an already stale entry, the entry will exist in the
cache.
2020-10-30 11:08:38 +01:00
Amaury Denoyelle
bc0af6a199 BUG/MINOR: lua: initialize sample before using it
Memset the sample before using it through hlua_lua2smp. This function is
ORing the smp.flags, so this field need to be cleared before its use.
This was reported by a coverity warning.

Fixes the github issue #929.
This bug can be backported up to 1.8.
2020-10-29 18:52:44 +01:00
Amaury Denoyelle
e6ba7915eb BUG/MINOR: server: fix down_time report for stats
Adjust condition used to report down_time for statistics. There was a
tiny probabilty to have a negative downtime if last_change was superior
to now. If this is the case, return only down_time.

This bug can backported up to 1.8.
2020-10-29 18:52:39 +01:00
Amaury Denoyelle
fe2bf091f6 BUG/MINOR: server: fix srv downtime calcul on starting
When a server is up after a failure, its downtime was reset to 0 on the
statistics. This is due to a wrong condition that causes srv.down_time
to never be set. Fix this by updating down_time each time the server is in
STARTING state.

Fixes the github issue #920.
This bug can be backported up to 1.8.
2020-10-29 18:52:18 +01:00
Amaury Denoyelle
66942c1d4d MINOR: mux-h2: count open connections/streams on stats
Implement as a gauge h2 counters for currently open connections and
streams. The counters are decremented when closing the stream or the
connection.
2020-10-28 08:55:23 +01:00
Amaury Denoyelle
a8879238ce MINOR: mux-h2: report detected error on stats
Implement counters for h2 protocol error on connection or stream level.
Also count the total number of rst_stream and goaway frames sent by the
mux in response to a detected error.
2020-10-28 08:55:19 +01:00
Amaury Denoyelle
2dec1ebec2 MINOR: mux-h2: add stats for received frame types
Implement counters for h2 frame received based on their type for
HEADERS, DATA, SETTINGS, RST_STREAM and GOAWAY.
2020-10-28 08:55:16 +01:00
Amaury Denoyelle
c92697d977 MINOR: mux-h2: add counters instance to h2c
Add pointer to counters as a member for h2c structure. This pointer is
initialized on h2_init function. This is useful to quickly access and
manipulate the counters inside every h2 functions.
2020-10-28 08:55:11 +01:00
Amaury Denoyelle
3238b3f906 MINOR: mux-h2: register a stats module
Use statistics API to register a new stats module generating counters
on h2 module. The counters are attached to frontend/backend instances.
2020-10-28 08:55:07 +01:00
Remi Tricot-Le Breton
bf97121f1c MINOR: cache: Create res.cache_hit and res.cache_name sample fetches
Res.cache_hit sample fetch returns a boolean which is true when the HTTP
response was built out of a cache. The cache's name is returned by the
res.cache_name sample_fetch.

This resolves GitHub issue #900.
2020-10-27 18:25:43 +01:00
Remi Tricot-Le Breton
53161d81b8 MINOR: cache: Process the If-Modified-Since header in conditional requests
If a client sends a conditional request containing an If-Modified-Since
header (and no If-None-Match header), we try to compare the date with
the one stored in the cache entry (coming either from a Last-Modified
head, or a Date header, or corresponding to the first response's
reception time). If the request's date is earlier than the stored one,
we send a "304 Not Modified" response back. Otherwise, the stored is sent
(through a 200 OK response).

This resolves GitHub issue #821.
2020-10-27 18:10:25 +01:00
Remi Tricot Le Breton
27091b4dd0 MINOR: cache: Store the "Last-Modified" date in the cache_entry
In order to manage "If-Modified-Since" requests, we need to keep a
reference time for our cache entries (to which the conditional request's
date will be compared).
This reference is either extracted from the "Last-Modified" header, or
the "Date" header, or the reception time of the response (in decreasing
order of priority).
The date values are converted into seconds since epoch in order to ease
comparisons and to limit storage space.
2020-10-27 18:10:25 +01:00
Tim Duesterhus
e0142340b2 BUG/MINOR: cache: Check the return value of http_replace_res_status
Send the full body if the status `304` cannot be applied. This should be the
most graceful failure.

Specific for 2.3, no backport needed.
2020-10-27 17:01:49 +01:00
Ilya Shipitsin
b9b84a4b25 BUILD: ssl: more elegant OpenSSL early data support check
BorinSSL pretends to be 1.1.1 version of OpenSSL. It messes some
version based feature presense checks. For example, OpenSSL specific
early data support.

Let us change that feature detction to SSL_READ_EARLY_DATA_SUCCESS
macro check instead of version comparision.
2020-10-27 13:08:32 +01:00
Willy Tarreau
a0133fcf35 BUG/MINOR: log: fix risk of null deref on error path
Previous commit ae32ac74db ("BUG/MINOR: log: fix memory leak on logsrv
parse error") addressed one issue and introduced another one, the logsrv
pointer may also be null at the end of the function so we must test it
before deciding to dereference it.

This should be backported along with the patch above to 2.2.
2020-10-27 10:35:32 +01:00
Willy Tarreau
ae32ac74db BUG/MINOR: log: fix memory leak on logsrv parse error
In case of parsing error on logsrv, we can leave parse_logsrv() without
releasing logsrv->ring_name or smp_rgs. Let's free them on the error path.
This should fix issue #926 detected by Coverity.

The impact is only a tiny leak just before reporting a fatal error, so it
will essentially annoy valgrind.

This can be backported to 2.0 (just drop the ring part).
2020-10-27 09:55:00 +01:00
Emmanuel Hocdet
a73a222a98 BUG/MEDIUM: ssl: OCSP must work with BoringSSL
It's a regression from b3201a3e "BUG/MINOR: disable dynamic OCSP load
with BoringSSL". The origin bug is link to 76b4a12 "BUG/MEDIUM: ssl:
memory leak of ocsp data at SSL_CTX_free()": ssl_sock_free_ocsp()
shoud be in #ifndef OPENSSL_IS_BORINGSSL.
To avoid long #ifdef for small code, the BoringSSL part for ocsp load
is isolated in a simple #ifdef.

This must be backported in 2.2 and 2.1
2020-10-27 09:38:51 +01:00
William Dauchy
5e10e44bce CLEANUP: http_ana: remove unused assignation of att_beg
`att_beg` is assigned to `next` at the end of the `for` loop, but is
assigned to `prev` at the beginning of the loop, which is itself
assigned to `next` after each loop. So it represents a double
assignation for the same value. Also `att_beg` is not used after the end
of the loop.

this is a partial fix for github issue #923, all the others could
probably be marked as intentional to protect future changes.

no backport needed.

Signed-off-by: William Dauchy <wdauchy@gmail.com>
2020-10-26 15:00:09 +01:00
Willy Tarreau
b3250a268b BUG/MINOR: extcheck: add missing checks on extchk_setenv()
Issue #910 reports that we fail to check a few extchk_setenv() in the
child process. These are mostly harmless, but instead of counting on
the external check script to fail the dirty way, better fail cleanly
when detecting the failure.

This could probably be backported to all stable branches.
2020-10-24 13:07:39 +02:00
Willy Tarreau
5472aa50f1 BUG/MEDIUM: queue: fix unsafe proxy pointer when counting nbpend
As reported by Coverity in issue #917, commit 96bca33 ("OPTIM: queue:
decrement the nbpend and totpend counters outside of the lock")
introduced a bug when moving the increments outside of the loop,
because we can't always rely on the pendconn "p" here as it may
be null. We can retrieve the proxy pointer directly from s->proxy
instead. The same is true for pendconn_redistribute(), though the
last "p" pointer there was still valid. This patch fixes both.

No backport is needed, this was introduced just before 2.3-dev8.
2020-10-24 12:57:41 +02:00
Willy Tarreau
bd71510024 MINOR: stats: report server's user-configured weight next to effective weight
The "weight" column on the stats page is somewhat confusing when using
slowstart becaue it reports the effective weight, without being really
explicit about it. In some situations the user-configured weight is more
relevant (especially with long slowstarts where it's important to know
if the configured weight is correct).

This adds a new uweight stat which reports a server's user-configured
weight, and in a backend it receives the sum of all servers' uweights.
In addition it adds the mention of "effective" in a few descriptions
for the "weight" column (help and doc).

As a result, the list of servers in a backend is now always scanned
when dumping the stats. But this is not a problem given that these
servers are already scanned anyway and for way heavier processing.
2020-10-23 22:47:30 +02:00
William Lallemand
089c13850f MEDIUM: ssl: ssl-load-extra-del-ext work only with .crt
In order to be compatible with the "set ssl cert" command of the CLI,
this patch restrict the ssl-load-extra-del-ext to files with a ".crt"
extension in the configuration.

Related to issue #785.

Should be backported where 8e8581e ("MINOR: ssl: 'ssl-load-extra-del-ext'
removes the certificate extension") was backported.
2020-10-23 18:41:08 +02:00
Willy Tarreau
2fbe6940f4 MINOR: stats: indicate the number of servers in a backend's status
When dumping the stats page (or the CSV output), when many states are
mixed, it's hard to figure the number of up servers. But when showing
only the "up" servers or hiding the "maint" servers, there's no way to
know how many servers are configured, which is problematic when trying
to update server-templates.

What this patch does, for dumps in "up" or "no-maint" modes, is to add
after the backend's "UP" or "DOWN" state "(%d/%d)" indicating the number
of servers seen as UP to the total number of servers in the backend. As
such, seeing "UP (33/39)" immediately tells that there are 6 servers that
are not listed when using "up", or will let the client figure how many
servers are left once deducted the number of non-maintenance ones. It's
not done on default dumps so as not to disturb existing tools, which
already have all the information they need in the dump.
2020-10-23 18:11:30 +02:00
Willy Tarreau
3e32036701 MINOR: stats: also support a "no-maint" show stat modifier
"no-maint" is a bit similar to "up" except that it will only hide
servers that are in maintenance (or disabled in the configuration), and
not those that are enabled but failed a check. One benefit here is to
significantly reduce the output of the "show stat" command when using
large server-templates containing entries that are not yet provisioned.

Note that the prometheus exporter also has such an option which does
the exact same.
2020-10-23 18:11:24 +02:00
Willy Tarreau
65141ffc4f MINOR: stats: support the "up" output modifier for "show stat"
We already had it on the HTTP interface but it was not accessible on the
CLI. It can be very convenient to hide servers which are down, do not
resolve, or are in maintenance.
2020-10-23 18:11:24 +02:00
Willy Tarreau
8ae8c48eb0 MEDIUM: fwlc: re-enable per-server queuing up to maxqueue
Leastconn has the nice propery of being able to sort servers by their
current usage. It's really a shame to force all requests into the backend
queue when the algo would be able to also consider their current queue.

In order not to change existing behavior but extend it, this patch allows
leastconn to elect servers which are already full if they have an explicitly
configured maxqueue setting above zero and their queue hasn't reached that
threshold. This will significantly reduce the pressure in the backend queue
when queuing a lot with lots of servers.

A test on 8 threads with 100 servers configured with maxconn 1 jumped
from 165krps to 330krps with maxqueue 15 with this patch.

This partially undoes commit 82cd5c13a ("OPTIM: backend: skip LB when we
know the backend is full") but allows to scale much better even by setting
a single-digit maxqueue value. Some better heuristics could be used to
maintain the behavior of the bypass in the patch above, consisting in
keeping it if it's known that there is no server with a configured
maxqueue in the farm (or in the backend).
2020-10-22 18:30:25 +02:00
Willy Tarreau
8c855f6cff MINOR: leastconn: take the queue length into account when queuing servers
When servers are queued into the leastconn tree, it's important to also
consider their queue length. There could be some servers with lots of
queued requests that we don't want to hammer with extra connections. In
order not to add extra stress to the LB algorithm, we don't update the
value when adding to the queue, only when updating the connection count
(i.e. picking from the queue or releasing a connection). This will be
sufficient to significantly improve the fairness in such situations.
2020-10-22 18:30:18 +02:00
Willy Tarreau
96bca33d75 OPTIM: queue: decrement the nbpend and totpend counters outside of the lock
We don't need to do that inside the lock. However since the operation
used to be done in deep functions, we have to make it resurface closer
to visible parts. It remains reasonably self-contained in queue.c so
that's not that big of a deal. Some places (redistribute) could benefit
from a single operation for all counts at once. Others like
pendconn_process_next_strm() are still called with both locks held but
now it will be possible to change this.
2020-10-22 17:32:28 +02:00
Willy Tarreau
56c1cfb179 OPTIM: queue: make the nbpend counters atomic
Instead of incrementing, decrementing them and updating their max under
the lock, make them atomic and keep them out of the lock as much as
possible. For __pendconn_unlink_* it would be wide to decide to move
these counters outside of the function, inside the callers so that a
single atomic op can be done per counter even for groups of operations.
2020-10-22 17:32:28 +02:00
Willy Tarreau
c7eedf7a5a MINOR: queue: reduce the locked area in pendconn_add()
Similarly to previous changes, we know if we're dealing with a server
or proxy lock so let's directly lock at the finest possible places
there. It's worth noting that a part of the operation consisting in
an increment and update of a max could be done outside of the lock
using atomic ops and a CAS.
2020-10-22 17:32:28 +02:00
Willy Tarreau
3e3ae2524d MINOR: queue: split __pendconn_unlink() in per-srv and per-prx
The function is called with the lock held and does too many tests for
things that are already known from its callers. Let's split it in two
so that its callers call either the per-server or per-proxy function
depending on where the element is (since they had to determine it
prior to taking the lock).
2020-10-22 17:32:28 +02:00
Willy Tarreau
5503908bdc MINOR: proxy/cli: only take a read lock in "show errors"
There's no point having an exclusive lock here, nothing is modified.
2020-10-22 17:32:28 +02:00
Willy Tarreau
595e767030 MINOR: server: read-lock the cookie during srv_set_dyncookie()
No need to use an exclusive lock on the proxy anymore when reading its
setting, a read lock is enough. A few other places continue to use a
write-lock when modifying simple flags only in order to let this
function see a consistent value all along. This might be changed in
the future using barriers and local copies.
2020-10-22 17:32:28 +02:00
Willy Tarreau
ac66d6bafb MINOR: proxy; replace the spinlock with an rwlock
This is an anticipation of finer grained locking for the queues. For now
all lock places take a write lock so that there is no difference at all
with previous code.
2020-10-22 17:32:28 +02:00
Christopher Faulet
9a3d3fcb5d BUG/MAJOR: mux-h2: Don't try to send data if we know it is no longer possible
In h2_send(), if we are in a state where we know it is no longer possible to
send data, we must exit the sending loop to avoid any possiblity to loop
forever. It may happen if the mbuf ring is released while the H2_CF_MUX_MFULL
flag is still set. Here is a possible scenario to trigger the bug :

  1) The mbuf ring is full because we are unable to send data. The
     H2_CF_MUX_MFULL flag is set on the H2 connection.

  2) At this stage, the task timeout expires because the H2 connection is
     blocked. We enter in h2_timeout_task() function. Because the mbuf ring is
     full, we cannot send the GOAWAY frame. Thus the H2_CF_GOAWAY_FAILED flag is
     set. The H2 connection is not released yet because there is still a stream
     attached. Here we leave h2_timeout_task() function.

  3) A bit later, the H2 connection is woken up. If h2_process(), nothing is
     performed by the first attempt to send data, in h2_send(). Then, because
     the H2_CF_GOAWAY_FAILED flag is set, the mbuf ring is released. But the
     H2_CF_MUX_MFULL flag is still there. At this step a second attempt to send
     data is performed.

  4) In h2_send(), we try to send data in a loop. To exist this loop, done
     variable must be set to 1. Because the H2_CF_MUX_MFULL flag is set, we
     don't call h2_process_mux() and done is not updated. Because the mbuf ring
     is now empty, nothing is sent and the H2_CF_MUX_MFULL flag is never
     removed. Now, we loop forever... waiting for the watchdog.

To fix the bug, we now exit the loop if one of these conditions is true :

  - The H2_CF_GOAWAY_FAILED flag is set on the H2 connection
  - The CO_FL_SOCK_WR_SH flag is set on the underlying connection
  - The H2 connection is in the H2_CS_ERROR2 state

This patch should fix the issue #912 and most probably #875. It must be
backported as far as the 1.8.
2020-10-22 17:13:22 +02:00
Christopher Faulet
d6c48366b8 BUG/MINOR: http-ana: Don't send payload for internal responses to HEAD requests
When an internal response is returned to a client, the message payload must be
skipped if it is a reply to a HEAD request. The payload is removed from the HTX
message just before the message forwarding.

This bugs has been around for a long time. It was already there in the pre-HTX
versions. In legacy HTTP mode, internal errors are not parsed. So this bug
cannot be easily fixed. Thus, this patch should only be backported in all HTX
versions, as far as 2.0. However, the code has significantly changed in the
2.2. Thus in the 2.1 and 2.0, the patch must be entirely reworked.
2020-10-22 17:13:22 +02:00
Tim Duesterhus
6414cd1fc0 CLEANUP: compression: Make use of http_get_etag_type()
This commit makes the compressor use http_get_etag_type to validate the
ETag instead of using an ad-hoc condition.
2020-10-22 16:59:36 +02:00
Remi Tricot-Le Breton
6cb10384a3 MEDIUM: cache: Add support for 'If-None-Match' request header
Partial support of conditional HTTP requests. This commit adds the
support of the 'If-None-Match' header (see RFC 7232#3.2).
When a client specifies a list of ETags through one or more
'If-None-Match' headers, they are all compared to the one that might have
been stored in the corresponding http cache entry until one of them
matches.
If a match happens, a specific "304 Not Modified" response is
sent instead of the cached data. This response has all the stored
headers but no other data (see RFC 7232#4.1). Otherwise, the whole cached data
is sent.
Although unlikely in a GET/HEAD request, the "If-None-Match: *" syntax is
valid and also receives a "304 Not Modified" response (RFC 7434#4.3.2).

This resolves a part of GitHub issue #821.
2020-10-22 16:10:20 +02:00
Remi Tricot-Le Breton
dbb65b5a7a MEDIUM: cache: Store the ETag information in the cache_entry
When sent by a server for a given resource, the ETag header is
stored in the coresponding cache entry (as any other header). So in
order to perform future ETag comparisons (for subsequent conditional
HTTP requests), we keep the length of the ETag and its offset
relative to the start of the cache_entry.
If no ETag header exists, the length and offset are zero.
2020-10-22 16:10:20 +02:00
Remi Tricot-Le Breton
bcced09b91 MINOR: http: Add etag comparison function
Add a function that compares two etags that might be of different types.
If any of them is weak, the 'W/' prefix is discarded and a strict string
comparison is performed.

Co-authored-by: Tim Duesterhus <tim@bastelstu.be>
2020-10-22 16:06:20 +02:00
Willy Tarreau
1e690bb6c4 BUG/MEDIUM: server: support changing the slowstart value from state-file
If the slowstart value in a state file implies the latest state change
is within the slowstart period, we end up calling srv_update_status()
to reschedule the server's state change but its task is not yet
allocated and remains null, causing a crash on startup.

Make sure srv_update_status() supports being called with partially
initialized servers which do not yet have a task. If the task has to
be scheduled, it will necessarily happen after initialization since
it will result from a state change.

This should be backported wherever server-state is present.
2020-10-22 12:07:07 +02:00
Willy Tarreau
ef71f0194c BUG/MINOR: queue: properly report redistributed connections
In commit 5cd4bbd7a ("BUG/MAJOR: threads/queue: Fix thread-safety issues
on the queues management") the counter of transferred connections was
accidently lost, so that when a server goes down with connections in its
queue, it will always be reported that 0 connection were transferred.

This should be backported as far as 1.8 since the patch above was
backported there.
2020-10-21 12:04:53 +02:00
William Lallemand
8e8581e242 MINOR: ssl: 'ssl-load-extra-del-ext' removes the certificate extension
In issue #785, users are reporting that it's not convenient to load a
".crt.key" when the configuration contains a ".crt".

This option allows to remove the extension of the certificate before
trying to load any extra SSL file (.key, .ocsp, .sctl, .issuer etc.)

The patch changes a little bit the way ssl_sock_load_files_into_ckch()
looks for the file.
2020-10-20 18:25:46 +02:00
William Dauchy
835712ad90 BUG/MINOR: listener: close before free in listener_accept
safer to close handle before the object is put back in the global pool.

this was introduced by commit 9378bbe0be ("MEDIUM: listener:
use protocol->accept_conn() to accept a connection")

this should fix github issue #902

no backport needed.

Signed-off-by: William Dauchy <wdauchy@gmail.com>
2020-10-20 15:40:36 +02:00
Willy Tarreau
f42d794d96 MEDIUM: config: report that "nbproc" is deprecated
As previously discussed, nbproc usage is bad, deprecated, and scheduled
for removal in 2.5.

If "nbproc" is found with more than one process while nbthread is not
set, a warning will be emitted encouraging to remove it or to migrate
to nbthread instead. This makes sure the user has an opportunity to
both see the message and silence it.
2020-10-20 11:54:49 +02:00
Willy Tarreau
69a7b8fc6c CLEANUP: task: remove the unused and mishandled global_rqueue_size
This counter is only updated and never used, and in addition it's done
without any atomicity so it's very unlikely to be correct on multi-CPU
systems! Let's just remove it since it's not used.
2020-10-19 14:08:13 +02:00
Willy Tarreau
3d18498645 CLEANUP: threads: don't register an initcall when not debugging
It's a bit overkill to register an initcall to call a function to set
a lock to zero when not debugging, let's just declare the lock as
pre-initialized to zero.
2020-10-19 14:08:13 +02:00
Ilya Shipitsin
b3201a3e07 BUG/MINOR: disable dynamic OCSP load with BoringSSL
it was accidently enabled on BoringSSL while
actually it is not supported

wla: Fix part of the issue mentionned in #895.
It fixes build of boringSSL versions prior to commit
https://boringssl.googlesource.com/boringssl/+/49e9f67d8b7cbeb3953b5548ad1009d15947a523

Must be backported in 2.2.

Signed-off-by: William Lallemand <wlallemand@haproxy.org>
2020-10-19 11:00:51 +02:00
Willy Tarreau
4b6e3c284a MINOR: lb/chash: use a read lock in chash_get_server_hash()
When using a low hash-balance-factor value, it's possible to loop
many times trying to find the best server. Figures in the order of
100-300 times were observed for 1000 servers with a factor of 101
(which seems a bit excessive for such a large farm). Given that
there's nothing in that function that prevents multiple threads
from working in parallel, let's switch to a read lock. Tests on
8 threads show roughly a 2% performance increase with this.
2020-10-17 20:15:49 +02:00
Willy Tarreau
f76a21f78c MINOR: lb/first: use a read lock in fas_get_next_server()
The "first" algorithm creates a lot of contention because all threads
focus on the same server by definition (the first available one). By
turning the exclusive lock to a read lock in fas_get_next_server(),
the request rate increases by 16% for 8 threads when many servers are
getting close to their maxconn.
2020-10-17 19:49:49 +02:00
Willy Tarreau
58bc9c1ced MINOR: lb/leastconn: only take a read lock in fwlc_get_next_server()
This function doesn't change the tree, it only looks for the first
usable server, so let's do that under a read lock to limit the
situations like the ones described in issue #881 where finding a
usable server when dealing with lots of saturated ones can be
expensive. At least threads will now be able to look up in
parallel.

It's interesting to note that s->served is not incremented during the
server choice, nor is the server repositionned. So right now already,
nothing prevents multiple threads from picking the same server. This
will not cause a significant imbalance anyway given that the server
will automatically be repositionned at the right place, but this might
be something to improve in the future if it doesn't come with too high
a cost.

It also looks like the way a server's weight is updated could be
revisited so that the write lock gets tighter at the expense of a
short part of inconsistency between weights and servers still present
in the tree.
2020-10-17 19:37:40 +02:00
Willy Tarreau
ae99aeb135 MINOR: lb/map: use seek lock and read locks where appropriate
- map_get_server_hash() doesn't need a write lock since it only
  reads the array, let's only use a read lock here.

- map_get_server_rr() only needs exclusivity to adjust the rr_idx
  while looking for its entry. Since this one is not used by
  map_get_server_hash(), let's turn this lock to a seek lock that
  doesn't block reads.

With 8 threads, no significant performance difference was noticed
given that lookups are usually instant with this LB algo so the
lock contention is rare.
2020-10-17 19:04:27 +02:00
Willy Tarreau
cd10def825 MINOR: backend: replace the lbprm lock with an rwlock
It was previously a spinlock, and it happens that a number of LB algos
only lock it for lookups, without performing any modification. Let's
first turn it to an rwlock and w-lock it everywhere. This is strictly
identical.

It was carefully checked that every HA_SPIN_LOCK() was turned to
HA_RWLOCK_WRLOCK() and that HA_SPIN_UNLOCK() was turned to
HA_RWLOCK_WRUNLOCK() on this lock. _INIT and _DESTROY were updated too.
2020-10-17 18:51:41 +02:00
Christopher Faulet
26a52af642 BUG/MEDIUM: lb: Always lock the server when calling server_{take,drop}_conn
The server lock must be held when server_take_conn() and server_drop_conn()
lbprm callback functions are called. It is a documented prerequisite but it is
not always performed. It only affects leastconn and fas lb algorithm. Others
don't use these callback functions.

A race condition on the next pending effecive weight (next_eweight) may be
encountered with the leastconn lb algorithm. An agent check may set it to 0
while fwlc_srv_reposition() is called. The server is locked during the
next_eweight update. But because the server lock is not acquired when
fwlc_srv_reposition() is called, we may use it to recompute the server key,
leading to a division by 0.

This patch must be backported as far as 1.8.
2020-10-17 09:29:43 +02:00
Christopher Faulet
db2c17da60 BUG/MEDIUM: mux-h1: Get the session from the H1S when capturing bad messages
It is not guaranteed that the backend connection has an owner. It is set when
the connection is created. But when the connection is moved in a server idle
list, the connection owner is set to NULL and may never be set again. On the
other hand, when a mux is created or when a CS is attached, the session is
always defined. The H1 stream always keep a reference on it when it is
created. Thus, when a bad message is captured we should not rely on the
connection owner to retrieve the session. Instead we should get it from the H1
stream.
2020-10-16 19:53:17 +02:00
Christopher Faulet
2469eba20f BUG/MEDIUM: spoe: Unset variable instead of set it if no data provided
If an agent try to set a variable with the NULL data type, an unset is perform
instead to avoid undefined behaviors. Once decoded, such data are translated to
a sample with the type SMP_T_ANY. It is unexpected in HAProxy. When a variable
is set with such sample, no data are attached to the variable. Thus, when the
variable is retrieved later in the transaction, the sample data are
uninitialized, leading to undefined behaviors depending on how it is used. For
instance, it leads to a crash if the debug converter is used on such variable.

This patch should fix the issue #855. It must be backported as far as 1.8.
2020-10-16 19:53:17 +02:00
Amaury Denoyelle
7239c24986 MEDIUM: backend: reuse connection if using a static sni
Detect if the sni used a constant value and if so, allow to reuse this
connection for later sessions. Use a combination of SMP_USE_INTRN +
!SMP_F_VOLATILE to consider a sample as a constant value.

This features has been requested on github issue #371.
2020-10-16 17:48:01 +02:00
Amaury Denoyelle
2f0a797631 MINOR: ssl: add volatile flags to ssl samples
The ssl samples are not constant over time and change according to the
session. Add the flag SMP_F_VOL_SESS to indicate this.
2020-10-16 17:47:29 +02:00
Frdric Lcaille
baeb919177 BUG/MINOR: peers: Possible unexpected peer seesion reset after collisions.
During a peers session collision (two peer sessions opened on both side) we must
mark the peer the session of which will be shutdown as alive, if not ->reconnect
timer will be set with a wrong value if the synchro task expires after the peer
has been reconnected. This possibly leads to unexpected deconnections during handshakes.
Furthermore, this patch cancels any heartbeat tranmimission when a reconnection
is prepared.
2020-10-16 17:45:58 +02:00
Willy Tarreau
0aa5a5b175 BUILD: listener: avoir a build warning when threads are disabled
It's just a __decl_thread() that appeared before the last variable.
2020-10-16 17:43:04 +02:00
Willy Tarreau
d48ed6643b MEDIUM: task: use an upgradable seek lock when scanning the wait queue
Right now when running a configuration with many global timers (e.g. many
health checks), there is a lot of contention on the global wait queue
lock because all threads queue up in front of it to scan it.

With 2000 servers checked every 10 milliseconds (200k checks per second),
after 23 seconds running on 8 threads, the lock stats were this high:

  Stats about Lock TASK_WQ:
      write lock  : 9872564
      write unlock: 9872564 (0)
      wait time for write     : 9208.409 msec
      wait time for write/lock: 932.727 nsec
      read lock   : 240367
      read unlock : 240367 (0)
      wait time for read      : 149.025 msec
      wait time for read/lock : 619.991 nsec

i.e. ~5% of the total runtime spent waiting on this specific lock.

With upgradable locks we don't need to work like this anymore. We
can just try to upgade the read lock to a seek lock before scanning
the queue, then upgrade the seek lock to a write lock for each element
we want to delete there and immediately downgrade it to a seek lock.

The benefit is double:
  - all other threads which need to call next_expired_task() before
    polling won't wait anymore since the seek lock is compatible with
    the read lock ;

  - all other threads competing on trying to grab this lock will fail
    on the upgrade attempt from read to seek, and will let the current
    lock owner finish collecting expired entries.

Doing only this has reduced the wake_expired_tasks() CPU usage in a
very large servers test from 2.15% to 1.04% as reported by perf top,
and increased by 3% the health check rate (all threads being saturated).

This is expected to help against (and possibly solve) the problem
described in issue #875.
2020-10-16 17:15:54 +02:00
Willy Tarreau
3cfaa8d1e0 BUG/MEDIUM: task: bound the number of tasks picked from the wait queue at once
There is a theorical problem in the wait queue, which is that with many
threads, one could spend a lot of time looping on the newly expired tasks,
causing a lot of contention on the global wq_lock and on the global
rq_lock. This initially sounds bening, but if another thread does just
a task_schedule() or task_queue(), it might end up waiting for a long
time on this lock, and this wait time will count on its execution budget,
degrading the end user's experience and possibly risking to trigger the
watchdog if that lasts too long.

The simplest (and backportable) solution here consists in bounding the
number of expired tasks that may be picked from the global wait queue at
once by a thread, given that all other ones will do it as well anyway.

We don't need to pick more than global.tune.runqueue_depth tasks at once
as we won't process more, so this counter is updated for both the local
and the global queues: threads with more local expired tasks will pick
less global tasks and conversely, keeping the load balanced between all
threads. This will guarantee a much lower latency if/when wakeup storms
happen (e.g. hundreds of thousands of synchronized health checks).

Note that some crashes have been witnessed with 1/4 of the threads in
wake_expired_tasks() and, while the issue might or might not be related,
not having reasonable bounds here definitely justifies why we can spend
so much time there.

This patch should be backported, probably as far as 2.0 (maybe with
some adaptations).
2020-10-16 15:18:48 +02:00
Willy Tarreau
ba29687bc1 BUG/MEDIUM: proxy: properly stop backends
The proxy stopping mechanism was changed with commit 322b9b94e ("MEDIUM:
proxy: make stop_proxy() now use stop_listener()") so that it's now
entirely driven by the listeners. One thing was forgotten though, which
is that pure backends will not stop anymore since they don't have any
listener, and that it's necessary to stop them in order to stop the
health checks.

No backport is needed.
2020-10-16 15:16:17 +02:00
Willy Tarreau
233ad288cd CLEANUP: protocol: remove the now unused <handler> field of proto_fam->bind()
We don't need to specify the handler anymore since it's set in the
receiver. Let's remove this argument from the function and clean up
the remains of code that were still setting it.
2020-10-15 21:47:56 +02:00
Willy Tarreau
a74cb38e7c MINOR: protocol: register the receiver's I/O handler and not the protocol's
Now we define a new sock_accept_iocb() for socket-based stream protocols
and use it as a wrapper for listener_accept() which now takes a listener
and not an FD anymore. This will allow the receiver's I/O cb to be
redefined during registration, and more specifically to get rid of the
hard-coded hacks in protocol_bind_all() made for syslog.

The previous ->accept() callback in the protocol was removed since it
doesn't have anything to do with accept() anymore but is more generic.
A few places where listener_accept() was compared against the FD's IO
callback for debugging purposes on the CLI were updated.
2020-10-15 21:47:56 +02:00
Willy Tarreau
e140a6921f MINOR: log: set the UDP receiver's I/O handler in the receiver
The I/O handler is syslog_fd_handler(), let's set it when creating
the receivers.
2020-10-15 21:47:56 +02:00
Willy Tarreau
d2fb99f9d5 MINOR: protocol: add a default I/O callback and put it into the receiver
For now we're still using the protocol's default accept() function as
the I/O callback registered by the receiver into the poller. While
this is usable for most TCP connections where a listener is needed,
this is not suitable for UDP where a different handler is needed.

Let's make this configurable in the receiver just like the upper layer
is configurable for listeners. In order to ease stream protocols
handling, the protocols will now provide a default I/O callback
which will be preset into the receivers upon allocation so that
almost none of them has to deal with it.
2020-10-15 21:47:56 +02:00
Willy Tarreau
caa91de718 MEDIUM: listener: remove the second pass of fd manipulation at the end
The receiver FDs must not be manipulated by the listener_accept()
function anymore, it must exclusively rely on the job performed by
its listeners, as it is also the only way to keep the receivers
working for established connections regardless of the listener's
state (typically for multiplexed protocols like QUIC). This used
to be necessary when the FDs were adjusted at once only but now
that fd_done() is gone and the need for polling enabled by the
accept_conn() function which detects the EAGAIN, we have nothing
to do there to fixup any possible previous bad decision anymore.

Interestingly, as a side effect of making the code not depend on
the FD anymore, it also removes the need for a second lock, which
increase the accept rate by about 1% on 8 threads.
2020-10-15 21:47:56 +02:00
Willy Tarreau
9378bbe0be MEDIUM: listener: use protocol->accept_conn() to accept a connection
Now listener_accept() doesn't have to deal with the incoming FD anymore
(except for a little bit of side band stuff). It directly retrieves a
valid connection from the protocol layer, or receives a well-defined
error code that helps it decide how to proceed. This removes a lot of
hardly maintainable low-level code and opens the function to receive
new protocol stacks.
2020-10-15 21:47:56 +02:00
Willy Tarreau
344b8fcf87 MINOR: sockpair: implement sockpair_accept_conn() to accept a connection
This is the same as previous commit, but this time for the sockpair-
specific stuff, relying on recv_fd_uxst() instead of accept(), so the
code is simpler. The various errno cases are handled like for regular
sockets, though some of them will probably never happen, but this does
not hurt.
2020-10-15 21:47:56 +02:00
Willy Tarreau
f1dc9f2f17 MINOR: sock: implement sock_accept_conn() to accept a connection
The socket-specific accept() code in listener_accept() has nothing to
do there. Let's move it to sock.c where it can be significantly cleaned
up. It will now directly return an accepted connection and provide a
status code instead of letting listener_accept() deal with various errno
values. Note that this doesn't support the sockpair specific code.

The function is now responsible for dealing with its own receiver's
polling state and calling fd_cant_recv() when facing EAGAIN.

One tiny change from the previous implementation is that the connection's
sockaddr is now allocated before trying accept(), which saves a memcpy()
of the resulting address for each accept at the expense of a cheap
pool_alloc/pool_free on the final accept returning EAGAIN. This still
apparently slightly improves accept performance in microbencharks.
2020-10-15 21:47:56 +02:00
Willy Tarreau
7d053e4211 MINOR: sock: rename sock_accept_conn() to sock_accepting_conn()
This call was introduced by commit 5ced3e887 ("MINOR: sock: add
sock_accept_conn() to test a listening socket") but is actually quite
confusing because it makes one think the socket will accept a connection
(which is what we want to have in a new function) while it only tells
whether it's configured to accept connections. Let's call it
sock_accepting_conn() instead.

The same change was applied to sockpair which had the same issue.
2020-10-15 21:47:56 +02:00
Willy Tarreau
01ca149047 MINOR: session: simplify error path in session_accept_fd()
Now that this function is always called with an initialized connection
and that the control layer is always initialized, we don't need to play
games with fdtab[] to decide how to close, we can simply rely on the
regular close path using conn_ctrl_close(), which can be fused with
conn_xprt_close() into conn_full_close().

The code is cleaner because the FD is now used only for some
protocol-specific setup (that will eventually have to move) and to
try to send a hard-coded HTTP 500 error message on raw sockets.
2020-10-15 21:47:56 +02:00
Willy Tarreau
83efc320aa MEDIUM: listener: allocate the connection before queuing a new connection
Till now we would keep a per-thread queue of pending incoming connections
for which we would store:
  - the listener
  - the accepted FD
  - the source address
  - the source address' length

And these elements were first used in session_accept_fd() running on the
target thread to allocate a connection and duplicate them again. Doing
this induces various problems. The first one is that session_accept_fd()
may only run on file descriptors and cannot be reused for QUIC. The second
issue is that it induces lots of memory copies and that the listerner
queue thrashes a lot of cache, consuming 64 bytes per entry.

This patch changes this by allocating the connection before queueing it,
and by only placing the connection's pointer into the queue. Indeed, the
first two calls used to initialize the connection already store all the
information above, which can be retrieved from the connection pointer
alone. So we just have to pop one pointer from the target thread, and
pass it to session_accept_fd() which only needs the FD for the final
settings.

This starts to make the accept path a bit more transport-agnostic, and
saves memory and CPU cycles at the same time (1% connection rate increase
was noticed with 4 threads). Thanks to dividing the accept-queue entry
size from 64 to 8 bytes, its size could be increased from 256 to 1024
connections while still dividing the overall size by two. No single
queue full condition was met.

One minor drawback is that connection may be allocated from one thread's
pool to be used into another one. But this already happens a lot with
connection reuse so there is really nothing new here.
2020-10-15 21:47:56 +02:00
Willy Tarreau
9b7587a6af MINOR: connection: make sockaddr_alloc() take the address to be copied
Roughly half of the calls to sockadr_alloc() are made to copy an already
known address. Let's optionally pass it in argument so that the function
can handle the copy at the same time, this slightly simplifies its usage.
2020-10-15 21:47:56 +02:00
Willy Tarreau
0138f51f93 CLEANUP: fd: finally get rid of fd_done_recv()
fd_done_recv() used to be useful with the FD cache because it used to
allow to keep a file descriptor active in the poller without being
marked as ready in the cache, saving it from ringing immediately,
without incurring any system call. It was a way to make it yield
to wait for new events leaving a bit of time for others. The only
user left was the connection accepter (listen_accept()). We used
to suspect that with the FD cache removal it had become totally
useless since changing its readiness or not wouldn't change its
status regarding the poller itself, which would be the only one
deciding to report it again.

Careful tests showed that it indeed has exactly zero effect nowadays,
the syscall numbers are exactly the same with and without, including
when enabling edge-triggered polling.

Given that there's no more API available to manipulate it and that it
was directly called as an optimization from listener_accept(), it's
about time to remove it.
2020-10-15 21:47:56 +02:00
Willy Tarreau
e53e7ec9d9 CLEANUP: protocol: remove the ->drain() function
No protocol defines it anymore. The last user used to be the monitor-net
stuff that got partially broken already when the tcp_drain() function
moved to conn_sock_drain() with commit e215bba95 ("MINOR: connection:
make conn_sock_drain() work for all socket families") in 1.9-dev2.

A part of this will surely move back later when non-socket connections
arrive with QUIC but better keep the API clean and implement what's
needed in time instead.
2020-10-15 21:47:04 +02:00
Willy Tarreau
9e9919dd8b MEDIUM: proxy: remove obsolete "monitor-net"
As discussed here during 2.1-dev, "monitor-net" is totally obsolete:

   https://www.mail-archive.com/haproxy@formilux.org/msg35204.html

It's fundamentally incompatible with usage of SSL, and imposes the
presence of file descriptors with hard-coded syscalls directly in the
generic accept path.

It's very unlikely that anyone has used it in the last 10 years for
anything beyond testing. In the worst case if anyone would depend
on it, replacing it with "http-request return status 200 if ..." and
"mode http" would certainly do the trick.

The keyword is still detected as special by the config parser to help
users update their configurations appropriately.
2020-10-15 21:47:04 +02:00
Willy Tarreau
77e0daef9f MEDIUM: proxy: remove obsolete "mode health"
As discussed here during 2.1-dev, "mode health" is totally obsolete:

   https://www.mail-archive.com/haproxy@formilux.org/msg35204.html

It's fundamentally incompatible with usage of SSL, doesn't support
source filtering, and imposes the presence of file descriptors with
hard-coded syscalls directly in the generic accept path.

It's very unlikely that anyone has used it in the last 10 years for
anything beyond testing. In the worst case if anyone would depend
on it, replacing it with "http-request return status 200" and "mode
http" would certainly do the trick.

The keyword is still detected as special by the config parser to help
users update their configurations appropriately.
2020-10-15 21:47:04 +02:00
Amaury Denoyelle
46f041d7f8 MEDIUM: fcgi: remove conn from session on detach
FCGI mux is marked with HOL blocking. On safe reuse mode, the connection
using it are placed on the sessions instead of the available lists to
avoid sharing it with several clients. On detach, if they are no more
streams, remove the connection from the session before adding it to the
idle list. If there is still used streams, do not add it to available
list as it should be already on the session list.
2020-10-15 15:19:34 +02:00
Amaury Denoyelle
6b8daef56b MEDIUM: h2: remove conn from session on detach
H2 mux is marked with HOL blocking. On safe reuse mode, the connection
using it are placed on the sessions instead of the available lists to
avoid sharing it with several clients. On detach, if they are no more
streams, remove the connection from the session before adding it to the
idle list. If there is still used streams, do not add it to available
list as it should be already on the session list.
2020-10-15 15:19:34 +02:00
Amaury Denoyelle
0d21deaded MEDIUM: backend: add reused conn to sess if mux marked as HOL blocking
If a connection is using a mux protocol subject to HOL blocking, add it
to the session instead of the available list to avoid sharing it with
other clients on connection reuse.
2020-10-15 15:19:34 +02:00
Amaury Denoyelle
00464ab8f4 MEDIUM: backend: add new conn to session if mux marked as HOL blocking
When allocating a new session on connect_server, if the mux protocol is
marked as subject of HOL blocking, add it into session instead of
available list to avoid sharing it with other clients.
2020-10-15 15:19:34 +02:00
Amaury Denoyelle
3d3c0918dc MINOR: mux/connection: add a new mux flag for HOL risk
This flag is used to indicate if the mux protocol is subject to
head-of-line blocking problem.
2020-10-15 15:19:34 +02:00
Amaury Denoyelle
9c13b62b47 BUG/MEDIUM: connection: fix srv idle count on conn takeover
On server connection migration from one thread to another, the wrong
idle thread-specific counter is decremented. This bug was introduced
since commit 3d52f0f1f8 due to the
factorization with srv_use_idle_conn. However, this statement is only
executed from conn_backend_get. Extract the decrement from
srv_use_idle_conn in conn_backend_get and use the correct
thread-specific counter.

Rename the function to srv_use_conn to better reflect its purpose as it
is also used with a newly initialized connection not in the idle list.

As a side change, the connection insertion to available list has also
been extracted to conn_backend_get. This will be useful to be able to
specify an alternative list for protocol subject to HOL risk that should
not be shared between several clients.

This bug is only present in this release and thus do not need a backport.
2020-10-15 15:19:34 +02:00
Amaury Denoyelle
5f1ded5629 BUG/MINOR: connection: fix loop iter on connection takeover
The loop always missed one iteration due to the incrementation done on
the for check. Move the incrementation on the loop last statement to fix
this behaviour.

This bug has a very limited impact, not at all visible to the user, but
could be backported to 2.2.
2020-10-15 15:19:25 +02:00
Willy Tarreau
1a3770cbc7 BUG/MEDIUM: deinit: check fdtab before fdtab[fd].owner
When running a pure config check (haproxy -c) we go through the deinit
phase without having allocated fdtab, so we can't blindly dereference
it. The issue was added by recent commit ae7bc4a23 ("MEDIUM: deinit:
close all receivers/listeners before scanning proxies"), no backport is
needed.
2020-10-14 12:13:51 +02:00
Willy Tarreau
2f6f362756 CLEANUP: protocol: intitialize all of the sockaddr when disconnecting
In issue #894, Coverity suspects uninitialized values for a socket's
address whose family is AF_UNSPEC but it doesn't know that the address
is not used in this case. It's not on a critical path and working around
it is trivial, let's fully declare the address. We're doing it for both
TCP and UDP, because the same principle appears at two places.
2020-10-14 10:54:15 +02:00
Willy Tarreau
258b351704 BUG/MINOR: listener: detect and handle shared sockets stopped in other processes
It may happen that during a temporary listener pause resulting from a
SIGTTOU, one process gets one of its sockets disabled by another process
and will not be able to recover from this situation by itself. For the
protocols supporting this (TCPv4 and TCPv6 at the moment) this situation
is detectable, so when this happens, let's put the listener into the
PAUSED state so that it remains consistent with the real socket state.
One nice effect is that just sending the SIGTTIN signal to the process
is enough to recover the socket in this case.

There is no need to backport this, this behavior has been there forever
and the fix requires to reimplement the getsockopt() call there.
2020-10-13 18:15:33 +02:00
Willy Tarreau
85d2ba6b78 CLEANUP: unix: make use of sock_accept_conn() where relevant
This allows to get rid of one getsockopt(SO_ACCEPTCONN) in the binding
code.
2020-10-13 18:15:33 +02:00
Willy Tarreau
3e12de2cc6 CLEANUP: tcp: make use of sock_accept_conn() where relevant
This allows to get rid of two getsockopt(SO_ACCEPTCONN).
2020-10-13 18:15:33 +02:00
Willy Tarreau
cc8b653483 MINOR: sockpair: implement the .rx_listening function
For socket pairs we don't rely on a real listening socket but we need to
have a properly connected UNIX stream socket. This is what the new
sockpair_accept_conn() tries to report. Some corner cases like half
shutdown will still not be detected but that should be sufficient for
most cases we really care about.
2020-10-13 18:15:33 +02:00
Willy Tarreau
29185140db MINOR: protocol: make proto_tcp & proto_uxst report listening sockets
Now we introdce a new .rx_listening() function to report if a receiver is
actually a listening socket. The reason for this is to help detect shared
sockets that might have been broken by sibling processes.
2020-10-13 18:15:33 +02:00
Willy Tarreau
5ced3e8879 MINOR: sock: add sock_accept_conn() to test a listening socket
At several places we need to check if a socket is still valid and still
willing to accept connections. Instead of open-coding this, each time,
let's add a new function for this.
2020-10-13 18:15:33 +02:00
Willy Tarreau
8b6fc3d10e MINOR: proto-tcp: make use of connect(AF_UNSPEC) for the pause
Currently the suspend/resume mechanism for listeners only works on Linux
and we resort to a number of tricks involving shutdown+listen+shutdown
to try to detect failures on other operating systems that do not support
it. But on Linux connect(AF_UNSPEC) also works pretty well and is much
cleaner. It still doesn't work on other operating systems but the error
is easier to detect and appears safer. So let's switch to this.
2020-10-13 18:15:33 +02:00
Willy Tarreau
7c9f756dcc MINOR: fd: report an error message when failing initial allocations
When starting with a huge maxconn (say 1 billion), the only error seen
is "No polling mechanism available". This doesn't help at all to resolve
the problem. Let's add specific alerts for the failed mallocs. Now we can
get this instead:

  [ALERT] 286/154439 (23408) : Not enough memory to allocate 2000000033 entries for fdtab!

This may be backported as far as 2.0 as it helps debugging bad configurations.
2020-10-13 18:15:33 +02:00
Willy Tarreau
b1e600c9c5 BUG/MINOR: mux-h2: do not stop outgoing connections on stopping
There are reports of a few "SC" in logs during reloads when H2 is used
on the backend side. Christopher analysed this as being caused by the
proxy disabled test in h2_process(). As the comment says, this was done
for frontends only, and must absolutely not send a GOAWAY to the backend,
as all it will result in is to make newly queued streams fail.

The fix consists in simply testing the connection side before deciding
to send the GOAWAY.

This may be backported as far as 2.0, though for whatever reason it seems
to manifest itself only since 2.2 (probably due to changes in the outgoing
connection setup sequence).
2020-10-13 18:15:33 +02:00
Willy Tarreau
2bd0f8147b BUG/MINOR: init: only keep rlim_fd_cur if max is unlimited
On some operating systems, RLIM_INFINITY is set to -1 so that when the
hard limit on the number of FDs is set to unlimited, taking the MAX
of both values keeps rlim_fd_cur and everything works. But on other
systems this values is defined as the highest positive integer. This
is what was observed on a 32-bit AIX 5.1. The effect is that maxsock
becomes 2^31-1 and that fdtab allocation fails.

Note that a simple workaround consists in manually setting maxconn in
the global section.

Let's ignore unlimited as soon as we retrieve rlim_fd_max so that all
systems behave consistently.

This may be backported as far as 2.0, though it doesn't seem like it
has annoyed anyone.
2020-10-13 15:36:08 +02:00
Frdric Lcaille
3fc0fe05fd MINOR: peers: heartbeat, collisions and handshake information for "show peers" command.
This patch adds "coll" new counter and the heartbeat timer values to "show peers"
command. It also adds the elapsed time since the last handshake to new "last_hdshk"
new peer dump field.
2020-10-09 20:59:58 +02:00
Willy Tarreau
0a002df2c2 BUG/MINOR: proxy: respect the proper format string in sig_pause/sig_listen
When factoring out the pause/resume error messages in commit 775e00158
("MAJOR: signals: use protocol_pause_all() and protocol_resume_all()")
I forgot that ha_warning() and send_log() take a format string and not
just a const string. No backport is needed, this is 2.3-dev.
2020-10-09 19:26:27 +02:00
Willy Tarreau
ccf429960b MEDIUM: config: remove the deprecated and dangerous global "debug" directive
This one was scheduled for removal in 2.3 since 2.2-dev3 by commit
1b85785bc ("MINOR: config: mark global.debug as deprecated"). Let's
remove it now. It remains totally possible to use -d on the command
line though.
2020-10-09 19:18:45 +02:00
Willy Tarreau
ab0a5192a8 MEDIUM: config: mark "grace" as deprecated
This was introduced 15 years ago or so to delay the stopping of some
services so that a monitoring device could detect its port being down
before services were stopped. Since then, clean reloads were implemented
and this doesn't cope well with reload at all, preventing the new process
from seamlessly binding, and forcing processes to coexist with half-baked
configurations.

Now it has become a real problem because there's a significant code
portion in the proxies that is solely dedicated to this obsolete feature,
and dealing with its special cases eases the introduction of bugs in
other places so it's about time that it goes.

We could tentatively schedule its removal for 2.4 with a hard deadline
for 2.5 in any case.
2020-10-09 19:07:01 +02:00
Willy Tarreau
e03204c8e1 MEDIUM: listeners: implement protocol level ->suspend/resume() calls
Now we have ->suspend() and ->resume() for listeners at the protocol
level. This means that it now becomes possible for a protocol to redefine
its own way to suspend and resume. The default functions are provided for
TCP, UDP and unix, and they are pass-through to the receiver equivalent
as it used to be till now. Nothing was defined for sockpair since it does
not need to suspend/resume during reloads, hence it will succeed.
2020-10-09 18:44:37 +02:00
Willy Tarreau
7b2febde1d MINOR: listeners: split do_unbind_listener() in two
The inner part now goes into the protocol and is used to decide how to
unbind a given protocol's listener. The existing code which is able to
also unbind the receiver was provided as a default function that we
currently use everywhere. Some complex listeners like QUIC will use this
to decide how to unbind without impacting existing connections, possibly
by setting up other incoming paths for the traffic.
2020-10-09 18:44:37 +02:00
Willy Tarreau
f58b8db47b MEDIUM: receivers: add an rx_unbind() method in the protocols
This is used as a generic way to unbind a receiver at the end of
do_unbind_listener(). This allows to considerably simplify that function
since we can now let the protocol perform the cleanup. The generic code
was moved to sock.c, along with the conditional rx_disable() call. Now
the code also supports that the ->disable() function of the protocol
which acts on the listener performs the close itself and adjusts the
RX_F_BUOND flag accordingly.
2020-10-09 18:44:36 +02:00
Willy Tarreau
18c20d28d7 MINOR: listeners: move the LI_O_MWORKER flag to the receiver
This listener flag indicates whether the receiver part of the listener
is specific to the master or to the workers. In practice it's only used
by the master's CLI right now. It's used to know whether or not the FD
must be closed before forking the workers. For this reason it's way more
of a receiver's property than a listener's property, so let's move it
there under the name RX_F_MWORKER. The rest of the code remains
unchanged.
2020-10-09 18:43:05 +02:00
Willy Tarreau
75c98d166e CLEANUP: listeners: remove the do_close argument to unbind_listener()
And also remove it from its callers. This subtle distinction was added as
sort of a hack for the seamless reload feature but is not needed anymore
since the do_close turned unused since commit previous commit ("MEDIUM:
listener: let do_unbind_listener() decide whether to close or not").
This also removes the unbind_listener_no_close() function.
2020-10-09 18:41:56 +02:00
Willy Tarreau
374e9af358 MEDIUM: listener: let do_unbind_listener() decide whether to close or not
The listener contains all the information needed to decide to close on
unbind or not. The rule is the following (when we're not stopping):

  - worker process unbinding from a worker's FD with socket transfer enabled => keep
  - master process unbinding from a master's inherited FD => keep
  - master process unbinding from a master's FD => close
  - master process unbinding from a worker's FD => close
  - worker process unbinding from a master's FD => close
  - worker process unbinding from a worker's FD => close

Let's translate that into the function and stop using the do_close
argument that is a bit obscure for callers. It was not yet removed
to ease code testing.
2020-10-09 18:41:48 +02:00
Willy Tarreau
87acd4e848 BROKEN/MEDIUM: listeners: rework the unbind logic to make it idempotent
BROKEN: the failure rate on reg-tests/seamless-reload/abns_socket.vtc has
significantly increased for no obvious reason. It fails 99% of the time vs
10% before.

do_unbind_listener() is not logical and is not even idempotent. It must
not touch the fd if already -1, which also means not touch the receiver.
In addition, when performing a partial stop on a socket (not closing),
we know the socket remains in the listening state yet it's marked as
LI_ASSIGNED, which is confusing as it doesn't translate its real state.

With this change, we make sure that FDs marked for close end up in
ASSIGNED state and that those which are really bound and on which a
listen() was made (i.e. not pause) remain in LISTEN state. This is what
is closest to reality.

Ideally this function should become a default proto->unbind() one but
it may still keep a bit too much state logic to become generalized to
other protocols (e.g. QUIC).
2020-10-09 18:29:04 +02:00
Willy Tarreau
d6afb53bdc MEDIUM: listeners: always close master vs worker listeners
Right now in enable_listener(), we used to start all enabled
listeners then kill from the workers those that were for the master.
But this is incomplete. We must also close from the master the
listeners that are solely for workers, and do it before we even
start them. Otherwise we end up with a master responding to the
worker CLI connections if the listener remains in listen mode to
translate the socket's real state.

It doesn't seem like it could have caused bugs in the past because we
used to aggressively mark disabled listeners as LI_ASSIGNED despite
the fact that they were still bound and listening. If this patch were
ever seen as a candidate solution for any obscure bug, be careful in
that it subtly relies on the fact that fd_delete() doesn't close
inherited FDs anymore, otherwise that could break the master's ability
to pass inherited FDs on reloads.
2020-10-09 18:29:04 +02:00
Willy Tarreau
95a3460739 MINOR: listener: add a few BUG_ON() statements to detect inconsistencies
We must not have an fd==-1 when switching to certain states. This will
later disappear but for now it helps detecting inconsistencies.
2020-10-09 18:29:04 +02:00
Willy Tarreau
e122dc5316 MEDIUM: udp: implement udp_suspend() and udp_resume()
In Linux kernel's net/ipv4/udp.c there's a udp_disconnect() function
which is called when connecting to AF_UNSPEC, and which unhashes a
"connection". This property, which is also documented in connect(2)
both in Linux and Open Group's man pages for datagrams, is interesting
because it allows to reverse a connect() which is in fact a filter on
the source. As such we can suspend a receiver by making it connect to
itself, which will cause it not to receive any traffic anymore, letting
a new one receive it all, then resume it by breaking this connection.

This was tested to work well on Linux, other operating systems should
also be tested. Before this, sending a SIGTTOU to a process having a
UDP syslog forwarder would cause this error:

  [WARNING] 280/194249 (3268) : Paused frontend GLOBAL.
  [WARNING] 280/194249 (3268) : Some proxies refused to pause, performing soft stop now.
  [WARNING] 280/194249 (3268) : Proxy GLOBAL stopped (cumulated conns: FE: 0, BE: 0).
  [WARNING] 280/194249 (3268) : Proxy sylog-loadb stopped (cumulated conns: FE: 0, BE: 0).

With this change, it now proceeds just like with TCP listeners:

  [WARNING] 280/195503 (3885) : Paused frontend GLOBAL.
  [WARNING] 280/195503 (3885) : Paused frontend sylog-loadb.

And SIGTTIN also works:

  [WARNING] 280/195507 (3885) : Resumed frontend GLOBAL.
  [WARNING] 280/195507 (3885) : Resumed frontend sylog-loadb.

On Linux this also works with TCP listeners (which can then be resumed
using listen()) and established TCP sockets (which we currently kill
using setsockopt(so_linger)), both not being portable on other OSes.
UNIX sockets and ABNS sockets do not support it however (connect
always fails). This needs to be further explored to see if other OSes
might benefit from this to perform portable and reliable resets
particularly on the backend side.
2020-10-09 18:29:04 +02:00
Willy Tarreau
626f3a7beb MEDIUM: proxy: make soft_stop() stop most listeners using protocol_stop_now()
One difficulty in soft-stopping is to make sure not to forget unlisted
listeners. By first doing a pass using protocol_stop_now() we catch the
vast majority of them. The few remaining ones are the ones belonging to
a proxy having a grace period. For these ones, the proxy will arm its
stop_time timer and emit a log message.

Since neither UDP listeners nor peers use the grace period, we can already
get rid of the special cases there since we know they will have been stopped
by the protocols.
2020-10-09 18:29:04 +02:00
Willy Tarreau
02e8557e88 MINOR: protocol: add protocol_stop_now() to instant-stop listeners
This will instantly stop all listeners except those which belong to
a proxy configured with a grace time. This means that UDP listeners,
and peers will also be stopped when called this way.
2020-10-09 18:29:04 +02:00
Willy Tarreau
acde152175 MEDIUM: proxy: centralize proxy status update and reporting
There are multiple ways a proxy may switch to the disabled state,
but now it's essentially once it loses its last listener. Instead
of keeping duplicate code around and reporting the state change
before actually seeing it, we now report it at the moment it's
performed (from the last listener leaving) which allows to remove
the message from all other places.
2020-10-09 18:29:04 +02:00
Willy Tarreau
a389c9e1e3 MEDIUM: proxy: add mode PR_MODE_PEERS to flag peers frontends
For now we cannot easily distinguish a peers frontend from another one,
which will be problematic to avoid reporting them when stopping their
listeners. Let's add PR_MODE_PEERS for this. It's not supposed to cause
any issue since all non-HTTP proxies are handled similarly now.
2020-10-09 18:28:21 +02:00
Willy Tarreau
322b9b94e9 MEDIUM: proxy: make stop_proxy() now use stop_listener()
The function will stop the listeners using this method, which in turn will
ping back once it finishes disabling the proxy.
2020-10-09 18:28:18 +02:00
Willy Tarreau
caa7df1296 MINOR: listeners: add a new stop_listener() function
This function will be used to definitely stop a listener (e.g. during a
soft_stop). This is actually tricky because it may be called for a proxy
or for a protocol, both of which require locks and already hold some. The
function takes booleans indicating which ones are already held, hoping
this will be enough. It's not well defined wether proto->disable() and
proto->rx_disable() are supposed to be called with any lock held, and
they are used from do_unbind_listener() with all these locks. Some back
annotations ought to be added on this point.

The proxy's listeners count is updated, and the proxy is marked as
disabled and woken up after the last one is gone. Note that a
listener in listen state is already not attached anymore since it
was disabled.
2020-10-09 18:27:48 +02:00
Willy Tarreau
455585e3cd MINOR: listeners: count unstoppable jobs on creation, not deletion
We have to count unstoppable jobs which correspond to worker sockpairs, in
order to know when to count. However the way it's currently done is quite
awkward because these are counted when stopping making the stop mechanism
non-idempotent. This is definitely something we want to fix before stopping
by protocol or our listeners count will quickly go wrong. Now they are
counted when the listeners are created.
2020-10-09 18:25:14 +02:00
Willy Tarreau
b4c083f5bf MINOR: listeners: split delete_listener() in two versions
We'll need an already locked variant of this function so let's make
__delete_listener() which will be called with the protocol lock held
and the listener's lock held.
2020-10-09 11:27:30 +02:00
Willy Tarreau
4b51f42899 MEDIUM: listeners: now use the listener's ->enable/disable
At each place we used to manipulate the FDs directly we can now call
the listener protocol's enable/disable/rx_enable/rx_disable depending
on whether the state changes on the listener or the receiver. One
exception currently remains in listener_accept() which is a bit special
and which should be split into 2 or 3 parts in the various protocol
layers.

The test of fd_updt in do_unbind_listener() that was added by commit
a51885621 ("BUG/MEDIUM: listeners: Don't call fd_stop_recv() if fd_updt
is NULL.") could finally be removed since that part is correctly handled
in the low-level disable() function.

One disable() was added in resume_listener() before switching to LI_FULL
because rx_resume() enables polling on the FD for the receiver while
we want to disable it if the listener is full. There are different
ways to clean this up in the future. One of them could be to consider
that TCP receivers only act at the listener level. But in fact it does
not translate reality. The reality is that only the receiver is paused
and that the listener's state ought not be affected here. Ultimately
the resume_listener() function should be split so that the part
controlled by the protocols only acts on the receiver, and that the
receiver itself notifies the upper listener about the change so that
the listener protocol may decide to disable or enable polling. Conversely
the listener should automatically update its receiver when they share the
same state. Since there is no harm proceeding like this, let's keep this
for now.
2020-10-09 11:27:30 +02:00
Willy Tarreau
5ddf1ce9c4 MINOR: protocol: add a new pair of enable/disable methods for listeners
These methods will be used to enable/disable accepting new connections
so that listeners do not play with FD directly anymore. Since all the
currently supported protocols work on socket for now, these are identical
to the rx_enable/rx_disable functions. However they were not defined in
sock.c since it's likely that some will quickly start to differ. At the
moment they're not used.

We have to take care of fd_updt before calling fd_{want,stop}_recv()
because it's allocated fairly late in the boot process and some such
functions may be called very early (e.g. to stop a disabled frontend's
listeners).
2020-10-09 11:27:30 +02:00
Willy Tarreau
686fa3db50 MINOR: protocol: add a new pair of rx_enable/rx_disable methods
These methods will be used to enable/disable rx at the receiver level so
that callers don't play with FDs directly anymore. All our protocols use
the generic ones from sock.c at the moment. For now they're not used.
2020-10-09 11:27:30 +02:00
Willy Tarreau
e70c7977f2 MINOR: sock: provide a set of generic enable/disable functions
These will be used on receivers, to enable or disable receiving on a
listener, which most of the time just consists in enabling/disabling
the file descriptor.

We have to take care of the existence of fd_updt to know if we may
or not call fd_{want,stop}_recv() since it's not permitted in very
early boot.
2020-10-09 11:27:30 +02:00
Willy Tarreau
010fe151ce MINOR: listener: use the protocol's ->rx_resume() method when available
Instead of calling listen() for IPPROTO_TCP in resume_listener(), let's
call the protocol's ->rx_resume() method when defined, which does the same.
This removes another hard-dependency on the fd and underlying protocol
from the generic functions.
2020-10-09 11:27:30 +02:00
Willy Tarreau
58e6b71bb0 MINOR: protocol: implement an ->rx_resume() method
This one undoes ->rx_suspend(), it tries to restore an operational socket.
It was only implemented for TCP since it's the only one we support right
now.
2020-10-09 11:27:30 +02:00
Willy Tarreau
cb66ea60cf MINOR: protocol: replace ->pause(listener) with ->rx_suspend(receiver)
The ->pause method is inappropriate since it doesn't exactly "pause" a
listener but rather temporarily disables it so that it's not visible at
all to let another process take its place. The term "suspend" is more
suitable, since the "pause" is actually what we'll need to apply to the
FULL and LIMITED states which really need to make a pause in the accept
process. And it goes well with the use of the "resume" function that
will also need to be made per-protocol.

Let's rename the function and make it act on the receiver since it's
already what it essentially does, hence the prefix "_rx" to make it
more explicit.

The protocol struct was a bit reordered because it was becoming a real
mess between the parts related to the listeners and those for the
receivers.
2020-10-09 11:27:30 +02:00
Willy Tarreau
d7f331c8b8 MINOR: protocol: rename the ->listeners field to ->receivers
Since the listeners were split into receiver+listener, this field ought
to have been renamed because it's confusing. It really links receivers
and not listeners, as most of the time it's used via rx.proto_list!
The nb_listeners field was updated accordingly.
2020-10-09 11:27:30 +02:00
Willy Tarreau
dae0692717 CLEANUP: listeners: remove the now unused enable_all_listeners()
It's not used anymore since previous commit. The good thing is that
no more listener function now directly acts on a protocol.
2020-10-09 11:27:30 +02:00
Willy Tarreau
078e1c7102 CLEANUP: protocol: remove the ->enable_all method
It's not used anymore, now the listeners are enabled from
protocol_enable_all().
2020-10-09 11:27:30 +02:00
Willy Tarreau
5b95ae6b32 MINOR: protocol: directly call enable_listener() from protocol_enable_all()
protocol_enable_all() calls proto->enable_all() for all protocols,
which is always equal to enable_all_listeners() which in turn simply is
a generic loop calling enable_listener() always returning ERR_NONE. Let's
clean this madness by first calling enable_listener() directly from
protocol_enable_all().
2020-10-09 11:27:30 +02:00
Willy Tarreau
7834a3f70f MINOR: listeners: export enable_listener()
we'll soon call it from outside.
2020-10-09 11:27:30 +02:00
Willy Tarreau
d008009958 CLEANUP: listeners: remove unused disable_listener and disable_all_listeners
These ones have never been called, they were referenced by the protocol's
disable_all for some protocols but there are no traces of their use, so
in addition to not being sure the code works, it has never been tested.
Let's remove a bit of complexity starting from there.
2020-10-09 11:27:30 +02:00
Willy Tarreau
fb4ead8e8a CLEANUP: protocol: remove the ->disable_all method
This one has never been used, is only referenced by proto_uxst and
proto_sockpair, and it's not even certain it works at all. Let's
get rid of it.
2020-10-09 11:27:30 +02:00
Willy Tarreau
e53608b2cd MINOR: listeners: move fd_stop_recv() to the receiver's socket code
fd_stop_recv() has nothing to do in the generic listener code, it's per
protocol as some don't need it. For instance with abns@ it could even
lead to fd_stop_recv(-1). And later with QUIC we don't want to touch
the fd at all! It used to be that since commit f2cb169487 delegating
fd manipulation to their respective threads it wasn't possible to call
it down there but it's not the case anymore, so let's perform the action
in the protocol-specific code.
2020-10-09 11:27:30 +02:00
Willy Tarreau
fb76bd5ca6 BUG/MEDIUM: listeners: correctly report pause() errors
By using the same "ret" variable in the "if" block to test the return
value of pause(), the second one shadows the first one and when forcing
the result to zero in case of an error, it doesn't do anything. The
problem is that some listeners used to fail to pause in multi-process
mode and this was not reported, but their failure was automatically
resolved by the last process to pause. By properly checking for errors
we might now possibly report a race once in a while so we may have to
roll this back later if some users meet it.

The test on ==0 is wrong too since technically speaking a total stop
validates the need for a pause, but stops the listener so it's just
the resume that won't work anymore. We could switch to stopped but
it's an involuntary switch and the user will not know. Better then
mark it as paused and let the resume continue to fail so that only
the resume will eventually report an error (e.g. abns@).

This must not be backported as there is a risk of side effect by fixing
this bug, given that it hides other bugs itself.
2020-10-09 11:27:30 +02:00
Willy Tarreau
91c614dd0e MEDIUM: proto_tcp: make the pause() more robust in multi-process
In multi-process, the TCP pause is very brittle and we never noticed
it because the error was lost in the upper layers. The problem is that
shutdown() may fail if another process already did it, and will cause
a process to fail to pause.

What we do here in case of error is that we double-check the socket's
state to verify if it's still accepting connections, and if not, we
can conclude that another process already did the job in parallel.

The difficulty here is that we're trying to eliminate false positives
where some OSes will silently report a success on shutdown() while they
don't shut the socket down, hence this dance of shutw/listen/shutr that
only keeps the compatible ones. Probably that a new approach relying on
connect(AF_UNSPEC) would provide better results.
2020-10-09 11:27:30 +02:00
Willy Tarreau
1accacbcc3 CLEANUP: proxy: remove the now unused pause_proxies() and resume_proxies()
They're not used anymore, delete them before someone thinks about using
them again!
2020-10-09 11:27:30 +02:00
Willy Tarreau
775e00158a MAJOR: signals: use protocol_pause_all() and protocol_resume_all()
When temporarily pausing the listeners with SIG_TTOU, we now pause
all listeners via the protocols instead of the proxies. This has the
benefits that listeners are paused regardless of whether or not they
belong to a visible proxy. And for resuming via SIG_TTIN we do the
same, which allows to report binding conflicts and address them,
since the operation can be repeated on a per-listener basis instead
of a per-proxy basis.

While in appearance all cases were properly handled, it's impossible
to completely rule out the possibility that something broken used to
work by luck due to the scan ordering which is naturally different,
hence the major tag.
2020-10-09 11:27:30 +02:00
Willy Tarreau
09819d1118 MINOR: protocol: introduce protocol_{pause,resume}_all()
These two functions are used to pause and resume all listeners of
all protocols. They use the standard listener functions for this
so they're supposed to handle the situation gracefully regardless
of the upper proxies' states, and they will report completion on
proxies once the switch is performed.

It might be nice to define a particular "failed" state for listeners
that cannot resume and to count them on proxies in order to mention
that they're definitely stuck. On the other hand, the current
situation is retryable which is quite appreciable as well.
2020-10-09 11:27:30 +02:00
Willy Tarreau
58651b42fc MEDIUM: listener/proxy: make the listeners notify about proxy pause/resume
Till now, we used to call pause_proxy()/resume_proxy() to enable/disable
processing on a proxy, which is used during soft reloads. But since we want
to drive this process from the listeners themselves, we have to instead
proceed the other way around so that when we enable/disable a listener,
it checks if it changed anything for the proxy and notifies about updates
at this level.

The detection is made using li_ready=0 for pause(), and li_paused=0
for resume(). Note that we must not include any test for li_bound because
this state is seen by processes which share the listener with another one
and which must not act on it since the other process will do it. As such
the socket behind the FD will automatically be paused and resume without
its local state changing, but this is the limit of a multi-process system
with shared listeners.
2020-10-09 11:27:30 +02:00
Willy Tarreau
5d7f9ce831 MINOR: listeners: check the current listener earlier state in resume_listener()
It's quite confusing to have the test on LI_READY very low in the function
as it should be made much earlier. Just like with previous commit, let's
do it when entering. The additional states, however (limited, full) continue
to go through the whole function.
2020-10-09 11:27:30 +02:00
Willy Tarreau
9b3a932777 MINOR: listeners: check the current listener state in pause_listener()
It's better not to try to perform pause() actions on wrong states, so
let's check this and make sure that all callers are now safe. This
means that we must not try to pause a listener which is already paused
(e.g. it could possibly fail if the pause operation isn't idempotent at
the socket level), nor should we try it on earlier states.
2020-10-09 11:27:30 +02:00
Willy Tarreau
337c835d16 MEDIUM: proxy: merge zombify_proxy() with stop_proxy()
The two functions don't need to be distinguished anymore since they have
all the necessary info to act as needed on their listeners. Let's just
pass via stop_proxy() and make it check for each listener which one to
close or not.
2020-10-09 11:27:30 +02:00
Willy Tarreau
43ba3cf2b5 MEDIUM: proxy: remove start_proxies()
Its sole remaining purpose was to display "proxy foo started", which
has little benefit and pollutes output for those with plenty of proxies.
Let's remove it now.

The VTCs were updated to reflect this, because many of them had explicit
counts of dropped lines to match this message.

This is tagged as MEDIUM because some users may be surprized by the
loss of this quite old message.
2020-10-09 11:27:30 +02:00
Willy Tarreau
c3914d4fff MEDIUM: proxy: replace proxy->state with proxy->disabled
The remaining proxy states were only used to distinguish an enabled
proxy from a disabled one. Due to the initialization order, both
PR_STNEW and PR_STREADY were equivalent after startup, and they
would only differ from PR_STSTOPPED when the proxy is disabled or
shutdown (which is effectively another way to disable it).

Now we just have a "disabled" field which allows to distinguish them.
It's becoming obvious that start_proxies() is only used to print a
greeting message now, that we'd rather get rid of. Probably that
zombify_proxy() and stop_proxy() should be merged once their
differences move to the right place.
2020-10-09 11:27:30 +02:00
Willy Tarreau
1ad64acf6c CLEANUP: peers: don't use the PR_ST* states to mark enabled/disabled
The enabled/disabled config options were stored into a "state" field
that is an integer but contained only PR_STNEW or PR_STSTOPPED, which
is a bit confusing, and causes a dependency with proxies. This was
renamed to "disabled" and is used as a boolean. The field was also
moved to the end of the struct to stop creating a hole and fill another
one.
2020-10-09 11:27:30 +02:00
Willy Tarreau
b50bf046e8 MINOR: startup: don't rely on PR_STNEW to check for listeners
Instead of looking at listeners in proxies in PR_STNEW state, we'd
rather check for listeners in those not in PR_STSTOPPED as it's only
this state which indicates the proxy was disabled. And let's check
the listeners count instead of testing the list's head.
2020-10-09 11:27:30 +02:00
Willy Tarreau
f18d968830 MEDIUM: proxy: remove state PR_STPAUSED
This state was used to mention that a proxy was in PAUSED state, as opposed
to the READY state. This was causing some trouble because if a listener
failed to resume (e.g. because its port was temporarily in use during the
resume), it was not possible to retry the operation later. Now by checking
the number of READY or PAUSED listeners instead, we can accurately know if
something went bad and try to fix it again later. The case of the temporary
port conflict during resume now works well:

  $ socat readline /tmp/sock1
  prompt
  > disable frontend testme3

  > disable frontend testme3
  All sockets are already disabled.

  > enable frontend testme3
  Failed to resume frontend, check logs for precise cause (port conflict?).

  > enable frontend testme3

  > enable frontend testme3
  All sockets are already enabled.
2020-10-09 11:27:30 +02:00
Willy Tarreau
a17c91b37f MEDIUM: proxy: remove the PR_STERROR state
This state is only set when a pause() fails but isn't even set when a
resume() fails. And we cannot recover from this state. Instead, let's
just count remaining ready listeners to decide to emit an error or not.
It's more accurate and will better support new attempts if needed.
2020-10-09 11:27:30 +02:00
Willy Tarreau
6b3bf733dd MEDIUM: proxy: remove the unused PR_STFULL state
Since v1.4 or so, it's almost not possible anymore to set this state. The
only exception is by using the CLI to change a frontend's maxconn setting
below its current usage. This case makes no sense, and for other cases it
doesn't make sense either because "full" is a vague concept when only
certain listeners are full and not all. Let's just remove this unused
state and make it clear that it's not reported. The "ready" or "open"
states will continue to be reported without being misleading as they
will be opposed to "stop".
2020-10-09 11:27:30 +02:00
Willy Tarreau
efc0eec4c1 MINOR: proxy: maintain per-state counters of listeners
The proxy state tries to be synthetic but that doesn't work well with
many listeners, especially for transition phases or after a failed
pause/resume.

In order to address this, we'll instead rely on counters of listeners in
a given state for the 3 major states (ready, paused, listen) and a total
counter. We'll now be able to determine a proxy's state by comparing these
counters only.
2020-10-09 11:27:30 +02:00
Willy Tarreau
a37b244509 MINOR: listeners: introduce listener_set_state()
This function is used as a wrapper to set a listener's state everywhere.
We'll use it later to maintain some counters in a consistent state when
switching state so it's capital that all state changes go through it.
No functional change was made beyond calling the wrapper.
2020-10-09 11:27:30 +02:00
Willy Tarreau
bec7ab0ad9 CLEANUP: proxy: remove the first_to_listen hack in zombify_proxy()
This thing was needed for an optimization used in soft_stop() which
doesn't exist anymore, so let's remove it as it's cryptic and hinders
the listeners cleanup.
2020-10-09 11:27:29 +02:00
Willy Tarreau
987dbf5bab MINOR: listeners: do not uselessly try to close zombie listeners in soft_stop()
The loop doesn't match anymore since the non-started listeners are in
LI_INIT and even if it had ever worked the benefit of closing zombies
at this point looks void at best.
2020-10-09 11:27:29 +02:00
Willy Tarreau
c6dac6c7f5 MEDIUM: listeners: remove the now unused ZOMBIE state
The zombie state is not used anymore by the listeners, because in the
last two cases where it was tested it couldn't match as it was covered
by the test on the process mask. Instead now the FD is either in the
LISTEN state or the INIT state. This also avoids forcing the listener
to be single-dimensional because actually belonging to another process
isn't totally exclusive with the other states, which explains some of
the difficulties requiring to check the proc_mask and the fd sometimes.

So let's get rid of it now not to be tempted to reuse it.

The doc on the listeners state was updated.
2020-10-09 11:27:29 +02:00
Willy Tarreau
ae7bc4a237 MEDIUM: deinit: close all receivers/listeners before scanning proxies
Because of the zombie state, proxies have a skewed vision of the state
of listeners, which explains why there are hacks switching the state
from ZOMBIE to INIT in the proxy cleaning loop. This is particularly
complicated and not needed, as all the information is now available
in the protocol list and the fdtab.

What we do here instead is to first close all active listeners or
receivers by protocol and clean their protocol parts. Then we scan the
fdtab to get rid of remaining ones that were necessarily in INIT state
after a previous invocation of delete_listener(). From this point, we
know the listeners are cleaned, the can safely be freed by scanning the
proxies.
2020-10-09 11:27:29 +02:00
Willy Tarreau
b6607bfaf0 MEDIUM: listeners: make unbind_listener() converge if needed
The ZOMBIE state on listener is a real mess. Listeners passing through
this state have lost their consistency with the proxy AND with the fdtab.
Plus this state is not used for all foreign listeners, only for those
belonging to a proxy that entirely runs on another process, otherwise it
stays in INIT state, which makes the usefulness extremely questionable.
But the real issue is that it's impossible to untangle the receivers
from the proxy state as long as we have this because of deinit()...

So what we do here is to start by making unbind_listener() support being
called more than once. This will permit to call it again to really close
the FD and finish the operations if it's called with an FD that's in a
fake state (such as INIT but with a valid fd).
2020-10-09 11:27:29 +02:00
Willy Tarreau
02b092f006 MEDIUM: init: stop disabled proxies after initializing fdtab
During the startup process we don't have any fdtab nor fd_updt for quite
a long time, and as such some operations on the listeners are not
permitted, such as fd_want_*/fd_stop_* or fd_delete(). The latter is of
particular concern because it's used when stopping a disabled frontend,
and it's performed very early during check_config_validity() while there
is no fdtab yet. The trick till now relies on the listener's state which
is a bit brittle.

There is absolutely no valid reason for stopping a proxy's listeners this
early, we can postpone it after init_pollers() which will at least have
allocated fdtab.
2020-10-09 11:27:29 +02:00
Willy Tarreau
cb89e32f31 MEDIUM: listeners: don't bounce listeners management between queues
During 2.1 development, commit f2cb16948 ("BUG/MAJOR: listener: fix
thread safety in resume_listener()") was introduced to bounce the
enabling/disabling of a listener's FD to one of its threads because
the remains of fd_update_cache() were fundamentally incompatible with
the need to call fd_want_recv() or fd_stop_recv() for another thread.

However since then we've totally dropped such code and it's totally
safe to use these functions on an FD that is solely used by another
thread (this is even used by the FD migration code). The only remaining
limitation concerning the wake up delay was addressed by previous commit
"MEDIUM: fd: always wake up one thread when enabling a foreing FD".

The current situation forces the FD management to remain in the
pause_listener() and resume_listener() functions just so that it can
bounce between threads, without having the ability to delegate it to
the suitable protocol layer.

So let's first remove this now unneeded workaround.
2020-10-09 11:27:29 +02:00
Willy Tarreau
f015887444 MEDIUM: fd: always wake up one thread when enabling a foreing FD
Since 2.2 it's safe to enable/disable another thread's FD but the fd_wake
calls will not immediately be considered because nothing wakes the other
threads up. This will have an impact on listeners when deciding to resume
them after they were paused, so at minima we want to wake up one of their
threads, just like the scheduler does on task_kill(). This is what this
patch does.
2020-10-09 11:27:29 +02:00
Christopher Faulet
b8d148a93f BUG/MINOR: http-htx: Expect no body for 204/304 internal HTTP responses
204 and 304 HTTP responses must no contain message body. These status codes are
correctly handled when the responses are received from a server. But there is no
specific processing for internal HTTP reponses (errorfile and http replies).

Now, when errorfiles or an http replies are parsed during the configuration
parsing, an error is triggered if a 204/304 message contains a body. An extra
check is also performed to ensure the body length matches the announce
content-length.

This patch should fix the issue #891. It must be backported as far as 2.0. For
2.1 and 2.0, only the http_str_to_htx() function must be fixed.
http_parse_http_reply() function does not exist.
2020-10-09 10:02:09 +02:00
Christopher Faulet
5563392554 BUG/MINOR: http: Fix content-length of the default 500 error
96 bytes is announce in the C-L header for a message of body of 97 bytes. This
bug was introduced by the patch 46a030cdd ("CLEANUP: assorted typo fixes in the
code and comments").

This patch must be backported in all versions where the patch above is (the 2.2
for now).
2020-10-09 10:02:09 +02:00
Christopher Faulet
aade4edc1a BUG/MEDIUM: mux-h2: Don't handle pending read0 too early on streams
This patch is similar to the previous one on the fcgi. Same is true for the
H2. But the bug is far harder to trigger because of the protocol cinematic. But
it may explain strange aborts in some edge cases.

A read0 received on the connection must not be handled too early by H2 streams.
If the demux buffer is not empty, the pending read0 must not be considered. The
H2 streams must not be passed in half-closed remote state in
h2s_wake_one_stream() and the CS_FL_EOS flag must not be set on the associated
conn-stream in h2_rcv_buf(). To sum up, it means, if there are still data
pending in the demux buffer, no abort must be reported to the streams.

To fix the issue, a dedicated function has been added, responsible for detecting
pending read0 for a H2 connection. A read0 is reported only if the demux buffer
is empty. This function is used instead of conn_xprt_read0_pending() at some
places.

Note that the HREM stream state should not be used to report aborts. It is
performed on h2s_wake_one_stream() function and it is a legacy of the very first
versions of the mux-h2.

This patch should be backported as far as 2.0. In the 1.8, the code is too
different to apply it like that. But it is probably useless because the mux-h2
can only be installed on the client side.
2020-10-09 10:02:09 +02:00
Christopher Faulet
6670e3e2bf BUG/MEDIUM: mux-fcgi: Don't handle pending read0 too early on streams
A read0 received on the connection must not be handled too early by FCGI
streams. If the demux buffer is not empty, the pending read0 must not be
considered. The FCGI streams must not be passed in half-closed remote state in
fcgi_strm_wake_one_stream() and the CS_FL_EOS flag must not be set on the
associated conn-stream in fcgi_rcv_buf(). To sum up, it means, if there are
still data pending in the demux buffer, no abort must be reported to the
streams.

To fix the issue, a dedicated function has been added, responsible for detecting
pending read0 for a FCGI connection. A read0 is reported only if the demux
buffer is empty. This function is used instead of conn_xprt_read0_pending() at
some places.

This patch should fix the issue #886. It must be backported as far as 2.1.
2020-10-09 10:02:00 +02:00
Emeric Brun
b0c331f71f BUG/MINOR: proxy/log: frontend/backend and log forward names must differ
This patch disallow to use same name for a log forward section
and a frontend/backend section.
2020-10-08 08:53:26 +02:00
Emeric Brun
cbb7bf7dd1 MEDIUM: log: syslog TCP support on log forward section.
This patch re-introduce the "bind" statement on log forward
sections to handle syslog TCP listeners as defined in
rfc-6587.

As complement it introduce "maxconn", "backlog" and "timeout
client" statements to parameter those listeners.
2020-10-07 17:17:27 +02:00
Emeric Brun
6d75616951 MINOR: channel: new getword and getchar functions on channel.
This patch adds two new functions to get a char
or a word from a channel.
2020-10-07 17:17:27 +02:00
Emeric Brun
2897644ae5 MINOR: stats: inc req counter on listeners.
This patch enables count of requests for listeners
if listener's counters are enabled.
2020-10-07 17:17:27 +02:00
Emeric Brun
c47ba59d1e BUG/MEDIUM: log: old processes with log foward section don't die on soft stop.
Old processes didn't die if a log foward section is declared and
a soft stop is requested.

This patch fix this issue and should be backpored in banches including
the log forward feature.
2020-10-07 17:17:27 +02:00
Emeric Brun
a39ecbdac1 BUG/MINOR: proxy: inc req counter on new syslog messages.
Increase req counter instead of conn counter on
new syslog messages.

This should be backported on branches including the
syslog forward feature.
2020-10-07 17:17:27 +02:00
Christopher Faulet
9589aa0fe5 CLEANUP: sock-unix: Remove an unreachable goto clause
Coverity reported dead code in sock_unix_bind_receiver() function. A goto clause
is unreachable because of the preceeding if/else block.

This patch should fix the issue #865. No backport needed.
2020-10-07 14:37:03 +02:00
Christopher Faulet
7b06d3adaa MINOR: mux-h1: Don't wakeup the H1C when output buffer become available
There is no reason to wake up the H1 connection when a new output buffer is
retrieved after an allocation failure because only the H1 stream will fill it.
2020-10-07 14:07:29 +02:00
Christopher Faulet
e9da975aab BUG/MINOR: mux-h1: Always set the session on frontend h1 stream
The session is always defined for a frontend connection. When a new client
connection is established, the session is set for the first H1 stream. But on
keep-alived connections, it is not set for the followings H1 streams while it is
possible.

This patch is tagged as a bug because it fixes an inconsistency in the H1
streams creation. But it does not fixed a known bug.

This patch must be backported as far as 2.0.
2020-10-07 14:07:29 +02:00
Christopher Faulet
69f2cb8df3 BUG/MINOR: mux-h1: Be sure to only set CO_RFL_READ_ONCE for the first read
The condition to set CO_RFL_READ_ONCE flag is not really accurate. We must check
the request state on frontend connection only and, in the opposite, the response
state on backend connection only. Only the parsed side must be considered, not
the opposite one.

This patch must be backported to 2.2.
2020-10-07 14:07:29 +02:00
Christopher Faulet
58feb49ed2 CLEANUP: ssl: Release cached SSL sessions on deinit
On deinit, when the server SSL ctx is released, we must take care to release the
cached SSL sessions stored in the array <ssl_ctx.reused_sess>. There are
global.nbthread entries in this array, each one may have a pointer on a cached
session.

This patch should fix the issue #802. No backport needed.
2020-10-07 14:07:29 +02:00
Tim Duesterhus
d7c6e6a71d CLEANUP: cache: Fix leak of cconf->c.name during config check
During the config check, the post parsing is not performed. Thus, cache filters
are not fully initialized and their cache name are never released. To be able to
release them, a flag is now set when a cache filter is fully initialized. On
deinit, if the flag is not set, it means the cache name must be freed.

The patch should fix #849. No backport needed.

[Cf: Tim is the patch author, but I added the commit message]
2020-10-07 14:07:29 +02:00
Christopher Faulet
a10000305f BUG/MINOR: proto_tcp: Report warning messages when listeners are bound
When a TCP listener is bound, in the tcp_bind_listener() function, a warning
message may be reported and should be displayed on verbose mode. But the warning
message is actually lost if the socket is successfully bound because we don't
fill the <errmsg> variable in this case.

This patch should fix the issue #863. No backport is needed.
2020-10-07 14:07:16 +02:00
Frdric Lcaille
e7e2b21d27 BUG/MINOR: peers: Inconsistency when dumping peer status codes.
A peer connection status must be considered as valid only if there is an applet
which has been instantiated for the connection to the peer. So, ->statuscode
should be considered as the last known peer connection status from the last
connection to this peer if any. To reflect this, "statuscode" field of peer dump
is renamed to "last_statuscode".
This patch also add "active"/"inactive" field after the peer location type
("remote" or "local") if an applet has been instantiated for this peer connection
or not.

Thank you to Emeric for having noticed this issue.

Must be backported in >=1.9 version.
2020-10-07 07:27:01 +02:00
Amaury Denoyelle
27373f7f75 MINOR: stats: remove for loop declaration
Remove variable declaration inside a for-loop. This was introduced by my
patches serie of the implementation of dynamic stats. This is not
supported by older gcc, notably on the freebsd environment of the ci.
2020-10-05 17:55:40 +02:00
Amaury Denoyelle
fbd0bc98fe MINOR: dns/stats: integrate dns counters in stats
Use the new stats module API to integrate the dns counters in the
standard stats. This is done in order to avoid code duplication, keep
the code related to cli out of dns and use the full possibility of the
stats function, allowing to print dns stats in csv or json format.
2020-10-05 12:02:14 +02:00
Amaury Denoyelle
0b70a8a314 MINOR: stats: add config "stats show modules"
By default, hide the extra statistics on the html page. Define a new
flag STAT_SHMODULES which is activated if the config "stats show
modules" is set.
2020-10-05 12:02:14 +02:00
Amaury Denoyelle
e3f576c29e MINOR: stats: display extra proxy stats on the html page
Integrate the additional proxy stats on the html stats page. For each
module, a new column is displayed with the individual stats available as
a tooltip.
2020-10-05 12:02:14 +02:00
Amaury Denoyelle
d3700a7fda MINOR: stats: support clear counters for dynamic stats
Add a boolean 'clearable' on stats module structure. If set, it forces
all the counters to be reset on 'clear counters' cli command. If not,
the counters are reset only when 'clear counters all' is used.
2020-10-05 12:02:14 +02:00
Amaury Denoyelle
ee63d4bd67 MEDIUM: stats: integrate static proxies stats in new stats
This is executed on startup with the registered statistics module. The
existing statistics have been merged in a list containing all
statistics for each domain. This is useful to print all available
statistics in a generic way.

Allocate extra counters for all proxies/servers/listeners instances.
These counters are allocated with the counters from the stats modules
registered on startup.
2020-10-05 12:02:14 +02:00
Amaury Denoyelle
58d395e0d6 MEDIUM: stats: define an API to register stat modules
A stat module can be registered to quickly add new statistics on
haproxy. It must be attached to one of the available stats domain. The
register must be done using INITCALL on STG_REGISTER.

The stat module has a name which should be unique for each new module in
a domain. It also contains a statistics list with their name/desc and a
pointer to a function used to fill the stats from the module counters.

The module also provides the initial counters values used on
automatically allocated counters. The offset for these counters
are stored in the module structure.
2020-10-05 12:02:14 +02:00
Amaury Denoyelle
50660a894d MEDIUM: stats: add delimiter for static proxy stats on csv
Use the character '-' to mark the end of static statistics on proxy
domain. After this marker, the order of the fields is not guaranteed and
should be parsed with care.
2020-10-05 12:02:14 +02:00
Amaury Denoyelle
72b16e5173 MINOR: stats: define additional flag px cap on domain
This flag can be used to determine on what type of proxy object the
statistics should be relevant. It will be useful when adding dynamic
statistics. Currently, this flag is not used.
2020-10-05 12:02:14 +02:00
Amaury Denoyelle
072f97eddf MINOR: stats: define the concept of domain for statistics
The domain option will be used to have statistics attached to other
objects than proxies/listeners/servers. At the moment, only the PROXY
domain is available.

Add an argument 'domain' on the 'show stats' cli command to specify the
domain. Only 'domain proxy' is available now. If not specified, proxy
will be considered the default domain.

For HTML output, only proxy statistics will be displayed.
2020-10-05 12:02:14 +02:00
Christopher Faulet
f98d821b94 MINOR: hlua: Display debug messages on stderr only in debug mode
Debug Messages emitted in lua using core.Debug() or core.log() are now only
displayed on stderr if HAProxy is started in debug mode (-d parameter on the
command line). There is no change for other message levels.

This patch should fix the issue #879. It may be backported to all stable
versions.
2020-10-05 11:11:36 +02:00
Amaury Denoyelle
98b81cb393 REORG: stats: extract proxies dump loop in a function
Create a dedicated function to loop on proxies and dump them. This will
be clearer when other object will be dump as well.

This patch is needed to extend stat support to components other than
proxies objects.
2020-10-05 10:54:35 +02:00
Amaury Denoyelle
f34017bb74 REORG: stats: extract proxy json dump
Create a dedicated function to dump a proxy as a json content. This
patch will be needed when other types of objects will be available for
json dump.

This patch is needed to extend stat support to components other than
proxies objects.
2020-10-05 10:53:50 +02:00
Amaury Denoyelle
da5b6d1cd9 MINOR: stats: hide px/sv/li fields in applet struct
Use an opaque pointer to store proxy instance. Regroup server/listener
as a single opaque pointer. This has the benefit to render the structure
more evolutive to support statistics on other types of objects in the
future.

This patch is needed to extend stat support for components other than
proxies objects.

The prometheus module has been adapted for these changes.
2020-10-05 10:48:58 +02:00
Amaury Denoyelle
97323c9ed4 MINOR: stats: add stats size as a parameter for csv/json dump
Render the stats size parametric in csv/json dump functions. This is
needed for the future patch which provides dynamic stats. For now the
static value ST_F_TOTAL_FIELDS is provided.

Remove unused parameter px on stats_dump_one_line.

This patch is needed to extend stat support to components other than
proxies objects.
2020-10-05 09:06:10 +02:00
Amaury Denoyelle
3ca927e68f REORG: stats: export some functions
Un-mark stats_dump_one_line and stats_putchk as static and export them
in the header file. These functions will be reusable by other components to
print their statistics.

This patch is needed to extend stat support to components other than
proxies objects.
2020-10-05 09:06:10 +02:00
Amaury Denoyelle
a53ce4cc01 BUG/MINOR: stats: fix validity of the json schema
The json schema seems to be invalid when checking using the validator
from https://www.jsonschemavalidator.net/. Correct it using the
following specification :
http://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.9.1

The impact of the bug it not well known as I am not sure of how useful
the json schema is for users. It is probably not used at all or else
this bug would have been reported.

This should be backported up to 1.8.
2020-10-05 09:06:06 +02:00
William Lallemand
51f784bcf9 CLEANUP: ssl: "bundle" is not an OpenSSL wording
There is a confusion between the HAProxy bundle and OpenSSL. OpenSSL
does not have "bundles" but multiple certificates in the same store.

Fix a commentary in the crt-list code.
2020-10-02 18:11:47 +02:00
Christopher Faulet
f7177271f3 BUG/MINOR: tcpcheck: Set socks4 and send-proxy flags before the connect call
Since the health-check refactoring in the 2.2, the checks through a socks4 proxy
are broken. To fix this bug, CO_FL_SOCKS4 flag must be set on the connection
before calling the connect() callback function because this flags is checked to
use the right destination address. The same is done for the CO_FL_SEND_PROXY
flag for a consistency purpose.

A reg-test has been added to test the "check-via-socks4" directive.

This patch must be backported to 2.2.
2020-10-02 17:14:34 +02:00
Christopher Faulet
2079a4ad36 MEDIUM: tcp-rules: Warn if a track-sc* content rule doesn't depend on content
The warning is only emitted for HTTP frontend. Idea is to encourage the usage of
"tcp-request session" rules to track counters that does not depend on the
request content. The documentation has been updated accordingly.

The warning is important because since the multiplexers were added in the
processing chain, the HTTP parsing is performed at a lower level. Thus parsing
errors are detected in the multiplexers, before the stream creation. In HTTP/2,
the error is reported by the multiplexer itself and the stream is never
created. This difference has a certain number of consequences, one of which is
that HTTP request counting in stick tables only works for valid H2 request, and
HTTP error tracking in stick tables never considers invalid H2 requests but only
invalid H1 ones. And the aim is to do the same with the mux-h1. This change will
not be done for the 2.3, but the 2.4. At the end, H1 and H2 parsing errors will
be caught by the multiplexers, at the session level. Thus, tracking counters at
the content level should be reserved for rules using a key based on the request
content or those using ACLs based on the request content.

To be clear, a warning will be emitted for the following rules :

  tcp-request content track-sc0 src
  tcp-request content track-sc0 src if ! { src 10.0.0.0/24 }
  tcp-request content track-sc0 src if { ssl_fc }

But not for the following ones :

  tcp-request content track-sc0 req.hdr(host)
  tcp-request content track-sc0 src if { req.hdr(host) -m found }
2020-10-02 15:50:26 +02:00
Eric Salama
7cea6065ac BUG/MINOR: Fix several leaks of 'log_tag' in init().
We use chunk_initstr() to store the program name as the default log-tag.

If we use the log-tag directive in the config file, this chunk will be
destroyed and replaced. chunk_initstr() sets the chunk size to 0 so we
will free the chunk itself, but not its content.

This happens for a global section and also for a proxy.

We fix this by using chunk_initlen() instead of chunk_initstr().
We also check that the memory allocation was successfull, otherwise we quit.

This fixes github issue #850.
It can be backported as far as 1.9, with minor adjustments to includes.
2020-10-02 15:50:26 +02:00
William Dauchy
1d0206e71f MINOR: ssl: remove uneeded check in crtlist_parse_file
this condition is never true as we either break or goto error, so those
two lines could be removed in the current state of the code.

this is fixing github issue #862

Signed-off-by: William Dauchy <w.dauchy@criteo.com>
2020-10-02 15:43:01 +02:00
Tim Duesterhus
b9f6accc9e MINOR: ssl: Add error if a crt-list might be truncated
Similar to warning during the parsing of the regular configuration file
that was added in 2fd5bdb439 this patch adds
a warning to the parsing of a crt-list if the file does not end in a
newline (and thus might have been truncated).

The logic essentially just was copied over. It might be good to refactor
this in the future, allowing easy re-use within all line-based config
parsers.

see https://github.com/haproxy/haproxy/issues/860#issuecomment-693422936
see 0354b658f0

This should be backported as a warning to 2.2.
2020-10-02 12:29:03 +02:00
Tim Duesterhus
6d07fae3c0 CLEANUP: ssl: Use structured format for error line report during crt-list parsing
This reuses the known `parsing [%s:%d]:` from regular config file error
reporting.
2020-10-02 12:29:03 +02:00
Willy Tarreau
fe2cc41151 BUILD: tools: fix minor build issue on isspace()
Previous commit fa41cb679 ("MINOR: tools: support for word expansion
of environment in parse_line") introduced two new isspace() on a char
and broke the build on systems using an array disguised in a macro
instead of a function (like cygwin). Just use the usual cast.
2020-10-01 18:05:48 +02:00
Amaury Denoyelle
fa41cb6792 MINOR: tools: support for word expansion of environment in parse_line
Allow the syntax "${...[*]}" to expand an environment variable
containing several values separated by spaces as individual arguments. A
new flag PARSE_OPT_WORD_EXPAND has been added to toggle this feature on
parse_line invocation. In case of an invalid syntax, a new error
PARSE_ERR_WRONG_EXPAND will be triggered.

This feature has been asked on the github issue #165.
2020-10-01 17:24:14 +02:00
Willy Tarreau
82cd5c13a5 OPTIM: backend: skip LB when we know the backend is full
For some algos (roundrobin, static-rr, leastconn, first) we know that
if there is any request queued in the backend, it's because a previous
attempt failed at finding a suitable server after trying all of them.
This alone is sufficient to decide that the next request will skip the
LB algo and directly reach the backend's queue. Doing this alone avoids
an O(N) lookup when load-balancing on a saturated farm of N servers,
which starts to be very expensive for hundreds of servers, especially
under the lbprm lock. This change alone has increased the request rate
from 110k to 148k RPS for 200 saturated servers on 8 threads, and
fwlc_reposition_srv() doesn't show up anymore in perf top. See github
issue #880 for more context.

It could have been the same for random, except that random is performed
using a consistent hash and it only considers a small set of servers (2
by default), so it may result in queueing at the backend despite having
some free slots on unknown servers. It's no big deal though since random()
only performs two attempts by default.

For hashing algorithms this is pointless since we don't queue at the
backend, except when there's no hash key found, which is the least of
our concerns here.
2020-09-29 17:18:37 +02:00
Willy Tarreau
b88ae18021 OPTIM: backend/random: never queue on the server, always on the backend
If random() returns a server whose maxconn is reached or the queue is
used, instead of adding the request to the server's queue, better add
it to the backend queue so that it can be served by any server (hence
the fastest one).
2020-09-29 17:18:11 +02:00
William Lallemand
20b0fed28c BUG/MINOR: ssl/crt-list: exit on warning out of crtlist_parse_line()
We should not exits on error out of the crtlist_parse_line() function.
The cfgerr error must be checked with the ERR_CODE mask.

Must be backported in 2.2.
2020-09-28 15:48:54 +02:00
Miroslav Zagorac
a6aca669b5 BUILD: trace: include tools.h
If the TRACE option is used when compiling the haproxy source,
the following error occurs on debian 9.13:

src/calltrace.o: In function `make_line':
.../src/calltrace.c:204: undefined reference to `rdtsc'
src/calltrace.o: In function `calltrace':
.../src/calltrace.c:277: undefined reference to `rdtsc'
collect2: error: ld returned 1 exit status
Makefile:866: recipe for target 'haproxy' failed
2020-09-25 17:54:48 +02:00
Willy Tarreau
82cd028d71 BUG/MINOR: listeners: properly close listener FDs
The code dealing with zombie proxies in soft_stop() is bogus, it uses
close() instead of fd_delete(), leaving a live entry in the fdtab with
a dangling pointer to a free memory location. The FD might be reassigned
for an outgoing connection for the time it takes the proxy to completely
stop, or could be dumped on the CLI's "show fd" command. In addition,
the listener's FD was not even reset, leaving doubts about whether or
not it will happen again in deinit().

And in deinit(), the loop in charge of closing zombie FDs is particularly
unsafe because it closes the fd then calls unbind_listener() then
delete_listener() hoping none of them will touch it again. Since it
requires some mental efforts to figure what's done there, let's correctly
reset the fd here as well and close it using fd_delete() to eliminate any
remaining doubts.

It's uncertain whether this should be backported. Zombie proxies are rare
and the situations capable of triggering such issues are not trivial to
setup. However it's easy to imagine how things could go wrong if backported
too far. Better wait for any matching report if at all (this code has been
there since 1.8 without anobody noticing).
2020-09-25 13:46:47 +02:00
Willy Tarreau
02e1975c29 BUG/MEDIUM: listeners: do not pause foreign listeners
There's a nasty case with listeners that belong to foreign processes.
If a proxy is defined this way:

     global
         nbproc 2

     frontend f
         bind :1111 process 1
         bind :2222 process 2

and if stats expose-fd listeners is set, the listeners' FDs will not
be closed on the processes that don't use them. At this point it's not
a big deal, except that they're shared between processes and that a
"disable frontend f" issued on one process will pause all of them and
cause the other process to see accept() fail, turning its own listener
to state LI_LIMITED to try to leave it some time to recover. But it
will never recover, even after an enable.

The root cause of the issue is that the ZOMBIE state doesn't cover
this situation since it's only for a proxy being entirely bound to a
process.

What we do here to address this is that we refrain from pausing a
file descriptor that belongs to a foreign process in pause_listener().
This definitely solves the problem. A similar test is present in
resume_listener() and is the reason why the FD doesn't recover upon the
"enable" action by the way.

This ought to be backported to 1.8 where seamless reload was integrated.

The config above should be sufficient to validate that the fix works;
after a pair of "disable/enable frontend" no process will handle the
traffic to one of the ports anymore.
2020-09-25 13:46:47 +02:00
Willy Tarreau
57a374131c MINOR: backend: add a new "path-only" option to "balance uri"
Since we've fixed the way URIs are handled in 2.1, some users have started
to experience inconsistencies in "balance uri" between requests received
over H1 and the same ones received over H2. This is caused by the fact
that H1 rarely uses absolute URIs while H2 always uses them. Similar
issues were reported already around replace-uri etc, leading to "pathq"
recently being introduced, so this isn't new.

Here what this patch does is add a new option to "balance uri" to indicate
that the hashing should only start at the path and not cover the authority.
This makes H1 relative URIs and H2 absolute URI hashes equally again.

Some extra options could be added to normalize URIs by always hashing the
authority (or host) in front of them, which would make sure that both
absolute and relative requests provide the same hash. This is left for
later if needed.
2020-09-23 08:56:29 +02:00
Willy Tarreau
3d1119d225 MINOR: backend: make the "whole" option of balance uri take only one bit
We'll want to add other boolean options on "balance uri", so let's make
some room aside "whole" and make it take only one bit and not one int.
2020-09-23 08:05:47 +02:00
Amaury Denoyelle
36b536652f BUG/MINOR: config: Fix memory leak on config parse listen
This memory leak happens if there is two or more defaults section. When
the default proxy is reinitialized, the structure member containing the
config filename must be freed.

Fix github issue #851.
Should be backported as far as 1.6.
2020-09-18 16:17:09 +02:00
Eric Salama
1aab911017 BUG/MINOR: Fix memory leaks cfg_parse_peers
When memory allocation fails in cfg_parse_peers or when an error occurs
while parsing a stick-table, the temporary table and its id must be freed.

This fixes github issue #854. It should be backported as far as 2.0.
2020-09-18 12:06:08 +02:00
Christopher Faulet
d2414a23c4 BUG/MINOR: http-fetch: Don't set the sample type during the htx prefetch
A subtle bug was introduced by the commit a6d9879e6 ("BUG/MEDIUM: htx:
smp_prefetch_htx() must always validate the direction"), for the "method"
sample fetch only. The sample data type and the method id are always
overwritten because smp_prefetch_htx() function is called later in the
sample fetch evaluation. The bug is in the smp_prefetch_htx() function but
it is only visible for the "method" sample fetch, for an unknown method.

In fact, when smp_prefetch_htx() is called, the sample object is
altered. The data type is set to SMP_T_BOOL and, on success, the data value
is set to 1.  Thus, if the caller has already set some infos into the sample
object, they may be lost. AFAIK, there is no reason to do so. It is
inherited from the legacy HTTP code and I honestely don't known why it was
done this way. So, instead of fixing the "method" sample fetch to set useful
info after the call to smp_prefetch_htx() function, I prefer to not alter
the sample object in smp_prefetch_htx().

This patch must be backported as far as 2.0. On the 2.0, only the HTX part
must be fixed.
2020-09-18 11:06:24 +02:00
Willy Tarreau
bba7a4dafd BUG/MINOR: h2/trace: do not display "stream error" after a frame ACK
When sending a frame ACK, the parser state is not equal to H2_CS_FRAME_H
and we used to report it as an error, which is not true. In fact we should
only indicate when we skip remaining data.

This may be backported as far as 2.1.
2020-09-18 07:41:28 +02:00
Willy Tarreau
8520d87198 MINOR: h2/trace: also display the remaining frame length in traces
It's often missing when debugging, even though it's often zero for
control frames or after data are consumed.
2020-09-18 07:39:29 +02:00
Willy Tarreau
f2cda10b1d BUILD: sock_inet: include errno.h
I was careful to have it for sock_unix.c but missed it for sock_inet
which broke with commit 36722d227 ("MINOR: sock_inet: report the errno
string in binding errors") depending on the build options. No backport
is needed.
2020-09-17 14:02:01 +02:00
Willy Tarreau
3cd58bf805 MINOR: sock_unix: report the errno string in binding errors
Just like with previous patch, let's report UNIX socket binding errors
in plain text. we can now see for example:

  [ALERT] 260/083531 (13365) : Starting frontend f: cannot switch final and temporary UNIX sockets (Operation not permitted) [/tmp/root.sock]
  [ALERT] 260/083640 (13375) : Starting frontend f: cannot change UNIX socket ownership (Operation not permitted) [/tmp/root.sock]
2020-09-17 08:35:38 +02:00
Willy Tarreau
36722d2274 MINOR: sock_inet: report the errno string in binding errors
With the socket binding code cleanup it becomes easy to add more info to
error messages. One missing thing used to be the error string, which is
now added after the generic one, for example:

  [ALERT] 260/082852 (12974) : Starting frontend f: cannot bind socket (Permission denied) [0.0.0.0:4]
  [ALERT] 260/083053 (13292) : Starting frontend f: cannot bind socket (Address already in use) [0.0.0.0:4444]
  [ALERT] 260/083104 (13298) : Starting frontend f: cannot bind socket (Cannot assign requested address) [1.1.1.1:4444]
2020-09-17 08:32:17 +02:00
Willy Tarreau
eb8cfe6723 BUILD: sock_unix: add missing errno.h
It builds fine when openssl is enabled, but fails otherwise. No backport
is needed.
2020-09-16 22:15:40 +02:00
Willy Tarreau
af9609b4d1 MINOR: tools: drop listener detection hack from str2sa_range()
We used to resort to a trick to detect whether the caller was a listener
or an outgoing socket in order never to present an AF_CUST_UDP* socket
to a log server nor a nameserver. This is no longer necessary, the socket
type alone will be enough.
2020-09-16 22:08:08 +02:00
Willy Tarreau
2b5e0d8b6a MEDIUM: proto_udp: replace last AF_CUST_UDP* with AF_INET*
We don't need to cheat with the sock_domain anymore, we now always have
the SOCK_DGRAM sock_type as a complementary selector. This patch restores
the sock_domain to AF_INET* in the udp* protocols and removes all traces
of the now unused AF_CUST_*.
2020-09-16 22:08:08 +02:00
Willy Tarreau
b2ffc99bbd MEDIUM: tools: make str2sa_range() use protocol_lookup()
By doing so we can remove the hard-coded mapping from AF_INET to AF_CUST_UDP
but we still need to keep the test on the listeners as long as these dummy
families remain present in the code.
2020-09-16 22:08:08 +02:00
Willy Tarreau
910c64da96 MEDIUM: protocol: store the socket and control type in the protocol array
The protocol array used to be only indexed by socket family, which is very
problematic with UDP (requiring an extra family) and with the forthcoming
QUIC (also requiring an extra family), especially since that binds them to
certain families, prevents them from supporting dgram UNIX sockets etc.

In order to address this, we now start to register the protocols with more
info, namely the socket type and the control type (either stream or dgram).
This is sufficient for the protocols we have to deal with, but could also
be extended further if multiple protocol variants were needed. But as is,
it still fits nicely in an array, which is convenient for lookups that are
instant.
2020-09-16 22:08:08 +02:00
Willy Tarreau
a54553f74f MINOR: protocol: add the control layer type in the protocol struct
This one will be needed to more accurately select a protocol. It may
differ from the socket type for QUIC, which uses dgram at the socket
layer and provides stream at the control layer. The upper level requests
a control layer only so we need this field.
2020-09-16 22:08:08 +02:00
Willy Tarreau
65ec4e3ff7 MEDIUM: tools: make str2sa_range() check that the protocol has ->connect()
Most callers of str2sa_range() need the protocol only to check that it
provides a ->connect() method. It used to be used to verify that it's a
stream protocol, but it might be a bit early to get rid of it. Let's keep
the test for now but move it to str2sa_range() when the new flag PA_O_CONNECT
is present. This way almost all call places could be cleaned from this.

There's a strange test in the server address parsing code that rechecks
the family from the socket which seems to be a duplicate of the previously
removed tests. It will have to be rechecked.
2020-09-16 22:08:08 +02:00
Willy Tarreau
5fc9328aa2 MINOR: tools: make str2sa_range() directly return the protocol
We'll need this so that it can return pointers to stacked protocol in
the future (for QUIC). In addition this removes a lot of tests for
protocol validity in the callers.

Some of them were checked further apart, or after a call to
str2listener() and they were simplified as well.

There's still a trick, we can fail to return a protocol in case the caller
accepts an fqdn for use later. This is what servers do and in this case it
is valid to return no protocol. A typical example is:

   server foo localhost:1111
2020-09-16 22:08:08 +02:00
Willy Tarreau
9b3178df23 MINOR: listener: pass the chosen protocol to create_listeners()
The function will need to use more than just a family, let's pass it
the selected protocol. The caller will then be able to do all the fancy
stuff required to pick the best protocol.
2020-09-16 22:08:08 +02:00
Willy Tarreau
5e1779abbf MEDIUM: config: make str2listener() not accept datagram sockets anymore
str2listener() was temporarily hacked to support datagram sockets for
the log-forward listeners. This has has an undesirable side effect that
"bind udp@1.2.3.4:5555" was silently accepted as TCP for a bind line.

We don't need this hack anymore since the only user (log-forward) now
relies on str2receiver(). Now such an address will properly be rejected.
2020-09-16 22:08:08 +02:00
Willy Tarreau
26ff5dabc0 MINOR: log-forward: use str2receiver() to parse the dgram-bind address
Thanks to this we don't need to specify "udp@" as it's implicitly a
datagram type listener that is expected, so any AF_INET/AF_INET4 address
will work.
2020-09-16 22:08:08 +02:00
Willy Tarreau
aa333123f2 MINOR: cfgparse: add str2receiver() to parse dgram receivers
This is at least temporary, as the migration at once is way too difficuly.
For now it still creates listeners but only allows DGRAM sockets. This
aims at easing the split between listeners and receivers.
2020-09-16 22:08:08 +02:00
Willy Tarreau
62a976cd44 MINOR: tools: remove the central test for "udp" in str2sa_range()
Now we only rely on dgram type associated with AF_INET/AF_INET6 to infer
UDP4/UDP6. We still keep the hint based on PA_O_SOCKET_FD to detect that
the caller is a listener though. It's still far from optimal but UDP
remains rooted into the protocols and needs to be taken out first.
2020-09-16 22:08:08 +02:00
Willy Tarreau
3baec249b1 MEDIUM: tools: make str2sa_range() only report AF_CUST_UDP on listeners
For now only listeners can make use of AF_CUST_UDP and it requires hacks
in the DNS and logsrv code to remap it to AF_INET. Make str2sa_range()
smarter by detecting that it's called for a listener and only set these
protocol families for listeners. This way we can get rid of the hacks.
2020-09-16 22:08:08 +02:00
Willy Tarreau
e835bd8f91 MINOR: tools: start to distinguish stream and dgram in str2sa_range()
The parser now supports a socket type for the control layer and a possible
other one for the transport layer. Usually they are the same except for
protocols like QUIC which will provide a stream transport layer based on
a datagram control layer. The default types are preset based on the caller's
expectations, and may be refined using "stream+" and "dgram+" prefixes.

For now they were not added to the docuemntation because other changes
will probably happen around UDP as well. It is conceivable that "tcpv4@"
or "udpv6@" will appear later as aliases for "stream+ipv4" or "dgram+ipv6".
2020-09-16 22:08:08 +02:00
Willy Tarreau
a215be282d MEDIUM: tools: make str2sa_range() check for the sockpair's FD usability
Just like for inherited sockets, we want to make sure that FDs that are
mentioned in "sockpair@" are actually usable. Right now this test is
performed by the callers, but not everywhere. Typically, the following
config will fail if fd #5 is not bound:

  frontend
      bind sockpair@5

But this one will pass if fd #6 is not bound:

  backend
      server s1 sockpair@6

Now both will return an error in such a case:
   - 'bind' : cannot use file descriptor '5' : Bad file descriptor.
   - 'server s1' : cannot use file descriptor '6' : Bad file descriptor.

As such the test in str2listener() is not needed anymore (and it was
wrong by the way, as it used to test for the socket by overwriting the
local address with a new address that's made of the FD encoded on 16
bits and happens to still be at the same place, but that strictly
depends on whatever the kernel wants to put there).
2020-09-16 22:08:08 +02:00
Willy Tarreau
804f11fdf8 MINOR: config: do not test an inherited socket again
Since previous patch we know that a successfully bound fd@XXX socket
is returned as its own protocol family from str2sa_range() and not as
AF_CUST_EXISTING_FD anymore o we don't need to check for that case
in str2listener().
2020-09-16 22:08:08 +02:00
Willy Tarreau
6edc722093 MEDIUM: tools: make str2sa_range() resolve pre-bound listeners
When str2sa_range() is invoked for a bind or log line, and it gets a file
descriptor number, it will immediately resolve the socket's address (when
it's a socket) so that the address family, address and port are correctly
set. This will later allow to resolve some transport protocols that are
attached to existing FDs. For raw FDs (e.g. logs) and for socket pairs,
the FD number is still returned in the address, because we need the
underlying address management to complete the bind/listen/connect/whatever
needed. One immediate benefit is that passing a bad FD will now result in
one of these errors:

  'bind' : cannot use file descriptor '3' : Socket operation on non-socket.
  'bind' : socket on file descriptor '3' is of the wrong type.

Note that as of now, we never return a listening socket with a family of
AF_CUST_EXISTING_FD. The only case where this family is seen is for a raw
FD (e.g. logs).
2020-09-16 22:08:08 +02:00
Willy Tarreau
895992619d MINOR: log: detect LOG_TARGET_FD from the fd and not from the syntax
Now that we have the FD value reported we don't need to cheat and detect
"fd@" in the address, we can safely rely on the FD value.
2020-09-16 22:08:08 +02:00
Willy Tarreau
a93e5c7fae MINOR: tools: make str2sa_range() optionally return the fd
If a file descriptor was passed, we can optionally return it. This will
be useful for listening sockets which are both a pre-bound FD and a ready
socket.
2020-09-16 22:08:08 +02:00
Willy Tarreau
909c23b086 MINOR: listener: remove the inherited arg to create_listener()
This argument can now safely be determined from fd != -1, let's just
drop it.
2020-09-16 22:08:08 +02:00
Willy Tarreau
328199348b MINOR: tools: add several PA_O_* flags in str2sa_range() callers
These flags indicate whether the call is made to fill a bind or a server
line, or even just send/recv calls (like logs or dns). Some special cases
are made for outgoing FDs (e.g. pipes for logs) or socket FDs (e.g external
listeners), and there's a distinction between stream or dgram usage that's
expected to significantly help str2sa_range() proceed appropriately with
the input information. For now they are not used yet.
2020-09-16 22:08:08 +02:00
Willy Tarreau
8b0fa8f0ab MEDIUM: config: remove all checks for missing/invalid ports/ranges
Now that str2sa_range() checks for appropriate port specification, we
don't need to implement adhoc test cases in every call place, if the
result is valid, the conditions are met otherwise the error message is
appropriately filled.
2020-09-16 22:08:08 +02:00
Willy Tarreau
7f96a8474c MEDIUM: tools: make str2sa_range() validate callers' port specifications
Now str2sa_range() will enforce the caller's port specification passed
using the PA_O_PORT_* flags, and will return an error on failure. For
optional ports, values 0-65535 will be enforced. For mandatory ports,
values 1-65535 are enforced. In case of ranges, it is also verified that
the upper bound is not lower than the lower bound, as this used to result
in empty listeners.

I couldn't find an easy way to test this using VTC since the purpose is
to trigger parse errors, so instead a test file is provided as
tests/ports.cfg with comments about what errors are expected for each
line.
2020-09-16 22:08:08 +02:00
Willy Tarreau
809587635e MINOR: tools: add several PA_O_PORT_* flags in str2sa_range() callers
These flags indicate what is expected regarding port specifications. Some
callers accept none, some need fixed ports, some have it mandatory, some
support ranges, and some take an offset. Each possibilty is reflected by
an option. For now they are not exploited, but the goal is to instrument
str2sa_range() to properly parse that.
2020-09-16 22:08:07 +02:00
Willy Tarreau
cd3a5591f6 MINOR: tools: make str2sa_range() take more options than just resolve
We currently have an argument to require that the address is resolved
but we'll soon add more, so let's turn it into a bit field. The old
"resolve" boolean is now PA_O_RESOLVE.
2020-09-16 22:08:07 +02:00
Willy Tarreau
5a7beed67b CLEANUP: tools: make str2sa_range() less awful for fd@ and sockpair@
The code is built to match prefixes at one place and to parse the address
as a second step, except for fd@ and sockpair@ where the test first passes
via AF_UNSPEC that is changed again. This is ugly and confusing, so let's
proceed like for the other ones.
2020-09-16 22:08:07 +02:00
Willy Tarreau
a5b325f92c MINOR: protocol: add a real family for existing FDs
At some places (log fd@XXX, bind fd@XXX) we support using an explicit
file descriptor number, that is placed into the sockaddr for later use.
The problem is that till now it was done with an AF_UNSPEC family, which
is also used for other situations like missing info or rings (for logs).

Let's create an "official" family AF_CUST_EXISTING_FD for this case so
that we are certain the FD can be found in the address when it is set.
2020-09-16 22:08:07 +02:00
Willy Tarreau
1e984b73f0 CLEANUP: protocol: remove family-specific fields from struct protocol
This removes the following fields from struct protocol that are now
retrieved from the protocol family instead: .sock_family, .sock_addrlen,
.l3_addrlen, .addrcmp, .bind, .get_src, .get_dst.

This also removes the UDP-specific udp{,6}_get_{src,dst}() functions
which were referenced but not used yet. Their goal was only to remap
the original AF_INET* addresses to AF_CUST_UDP*.

Note that .sock_domain is still there as it's used as a selector for
the protocol struct to be used.
2020-09-16 22:08:07 +02:00
Willy Tarreau
f1f660978c MINOR: protocol: retrieve the family-specific fields from the family
We now take care of retrieving sock_family, l3_addrlen, bind(),
addrcmp(), get_src() and get_dst() from the protocol family and
not just the protocol itself. There are very few places, this was
only seldom used. Interestingly in sock_inet.c used to rely on
->sock_family instead of ->sock_domain, and sock_unix.c used to
hard-code PF_UNIX instead of using ->sock_domain.

Also it appears obvious we have something wrong it the protocol
selection algorithm because sock_domain is the one set to the custom
protocols while it ought to be sock_family instead, which would avoid
having to hard-code some conversions for UDP namely.
2020-09-16 22:08:07 +02:00
Willy Tarreau
b0254cb361 MINOR: protocol: add a new proto_fam structure for protocol families
We need to specially handle protocol families which regroup common
functions used for a given address family. These functions include
bind(), addrcmp(), get_src() and get_dst() for now. Some fields are
also added about the address family, socket domain (protocol family
passed to the socket() syscall), and address length.

These protocol families are referenced from the protocols but not yet
used.
2020-09-16 22:08:07 +02:00
Willy Tarreau
ad33acf838 MEDIUM: protocol: do not call proto->bind() anymore from bind_listener()
All protocol's listeners now only take care of themselves and not of
the receiver anymore since that's already being done in proto_bind_all().
Now it finally becomes obvious that UDP doesn't need a listener, as the
only thing it does is to set the listener's state to LI_LISTEN!
2020-09-16 22:08:07 +02:00
Willy Tarreau
fc974887ce MEDIUM: protocol: explicitly start the receiver before the listener
Now protocol_bind_all() starts the receivers before their respective
listeners so that ultimately we won't need the listeners for non-
connected protocols.

We still have to resort to an ugly trick to set the I/O handler in
case of syslog over UDP because for now it's still not set in the
receiver, so we hard-code it.
2020-09-16 22:08:07 +02:00
Willy Tarreau
9eda7a6d62 MEDIUM: proto_sockpair: make use of sockpair_bind_receiver()
Now we rely on the address family's receiver instead of binding everything
ourselves.
2020-09-16 22:08:07 +02:00
Willy Tarreau
62292b28a3 MEDIUM: sockpair: implement sockpair_bind_receiver()
Note that for now we don't have a sockpair.c file to host that unusual
family, so the new function was placed directly into proto_sockpair.c.
It's no big deal given that this family is currently not shared with
multiple protocols.

The function does almost nothing but setting up the receiver. This is
normal as the socket the FDs are passed onto are supposed to have been
already created somewhere else, and the only usable identifier for such
a socket pair is the receiving FD itself.

The function was assigned to sockpair's ->bind() and is not used yet.
2020-09-16 22:08:07 +02:00
Willy Tarreau
cd5e5eaf50 MEDIUM: uxst: make use of sock_unix_bind_receiver()
This removes all the AF_UNIX-specific code from uxst_bind_listener()
and now simply relies on sock_unix_bind_listener() to do the same
job. As mentionned in previous commit, the only difference is that
now an unlikely failure on listen() will not result in a roll back
of the temporary socket names since they will have been renamed
during the bind() operation (as expected). But such failures do not
correspond to any normal case and mostly denote operating system
issues so there's no functionality loss here.
2020-09-16 22:08:07 +02:00
Willy Tarreau
1e0a860099 MEDIUM: sock_unix: implement sock_unix_bind_receiver()
This function performs all the bind-related stuff for UNIX sockets that
was previously done in uxst_bind_listener(). There is a very tiny
difference however, which is that previously, in the unlikely event
where listen() would fail, it was still possible to roll back the binding
and rename the backup to the original socket. Now we have to rename it
before calling returning, hence it will be done before calling listen().
However, this doesn't cover any particular use case since listen() has no
reason to fail there (and the rollback is not done for inherited sockets),
that was just done that way as a generic error processing path.

The code is not used yet and is referenced in the uxst proto's ->bind().
2020-09-16 22:08:07 +02:00
Willy Tarreau
2f7687d0e8 MEDIUM: udp: make use of sock_inet_bind_receiver()
This removes all the AF_INET-specific code from udp_bind_listener()
and now simply relies on sock_inet_bind_listener() to do the same
job. The function is now basically just a wrapper around
sock_inet_bind_receiver().
2020-09-16 22:08:07 +02:00
Willy Tarreau
af9a7f5bb0 MEDIUM: tcp: make use of sock_inet_bind_receiver()
This removes all the AF_INET-specific code from tcp_bind_listener()
and now simply relies on sock_inet_bind_listener() to do the same
job. The function was now roughly cut in half and its error path
significantly simplified.
2020-09-16 22:08:07 +02:00
Willy Tarreau
d69ce1ffbc MEDIUM: sock_inet: implement sock_inet_bind_receiver()
This function collects all the receiver-specific code from both
tcp_bind_listener() and udp_bind_listener() in order to provide a more
generic AF_INET/AF_INET6 socket binding function. For now the API is
not very elegant because some info are still missing from the receiver
while there's no ideal place to fill them except when calling ->listen()
at the protocol level. It looks like some polishing code is needed in
check_config_validity() or somewhere around this in order to finalize
the receivers' setup. The main issue is that listeners and receivers
are created *before* bind_conf options are parsed and that there's no
finishing step to resolve some of them.

The function currently sets up a receiver and subscribes it to the
poller. In an ideal world we wouldn't subscribe it but let the caller
do it after having finished to configure the L4 stuff. The problem is
that the caller would then need to perform an fd_insert() call and to
possibly set the exported flag on the FD while it's not its job. Maybe
an improvement could be to have a separate sock_start_receiver() call
in sock.c.

For now the function is not used but it will soon be. It's already
referenced as tcp and udp's ->bind().
2020-09-16 22:08:07 +02:00
Willy Tarreau
b3580b19c8 MINOR: protocol: rename the ->bind field to ->listen
The function currently is doing both the bind() and the listen(), so
let's call it ->listen so that the bind() operation can move to another
place.
2020-09-16 22:08:07 +02:00
Willy Tarreau
c049c0d5ad MINOR: sock: make sock_find_compatible_fd() only take a receiver
We don't need to have a listener anymore to find an fd, a receiver with
its settings properly set is enough now.
2020-09-16 22:08:07 +02:00
Willy Tarreau
3fd3bdc836 MINOR: receiver: move the FOREIGN and V6ONLY options from listener to settings
The new RX_O_FOREIGN, RX_O_V6ONLY and RX_O_V4V6 options are now set into
the rx_settings part during the parsing, so that we don't need to adjust
them in each and every listener anymore. We have to keep both v4v6 and
v6only due to the precedence from v6only over v4v6.
2020-09-16 22:08:07 +02:00
Willy Tarreau
43046fa4f4 MINOR: listener: move the INHERITED flag down to the receiver
It's the receiver's FD that's inherited from the parent process, not
the listener's so the flag must move to the receiver so that appropriate
actions can be taken.
2020-09-16 22:08:07 +02:00
Willy Tarreau
0b9150155e MINOR: receiver: add a receiver-specific flag to indicate the socket is bound
In order to split the receiver from the listener, we'll need to know that
a socket is already bound and ready to receive. We used to do that via
tha LI_O_ASSIGNED state but that's not sufficient anymore since the
receiver might not belong to a listener anymore. The new RX_F_BOUND flag
is used for this.
2020-09-16 22:08:07 +02:00
Willy Tarreau
818a92e87a MINOR: listener: prefer to retrieve the socket's settings via the receiver
Some socket settings used to be retrieved via the listener and the
bind_conf. Now instead we use the receiver and its settings whenever
appropriate. This will simplify the removal of the dependency on the
listener.
2020-09-16 22:08:07 +02:00
Willy Tarreau
eef454224d MINOR: receiver: link the receiver to its owner
A receiver will have to pass a context to be installed into the fdtab
for use by the handler. We need to set this into the receiver struct
as the bind will happen longer after the configuration.
2020-09-16 22:08:07 +02:00
Willy Tarreau
0fce6bce34 MINOR: receiver: link the receiver to its settings
Just like listeners keep a pointer to their bind_conf, receivers now also
have a pointer to their rx_settings. All those belonging to a listener are
automatically initialized with a pointer to the bind_conf's settings.
2020-09-16 22:08:07 +02:00
Willy Tarreau
4dfabfed13 MINOR: listener: make sock_find_compatible_fd() check the socket type
sock_find_compatible_fd() can now access the protocol via the receiver
hence it can access its socket type and know whether the receiver has
dgram or stream sockets, so we don't need to hack around AF_CUST_UDP*
anymore there.
2020-09-16 22:08:07 +02:00
Willy Tarreau
b743661f04 REORG: listener: move the listener's proto to the receiver
The receiver is the one which depends on the protocol while the listener
relies on the receiver. Let's move the protocol there. Since there's also
a list element to get back to the listener from the proto list, this list
element (proto_list) was moved as well. For now when scanning protos, we
still see listeners which are linked by their rx.proto_list part.
2020-09-16 22:08:05 +02:00
Willy Tarreau
38ba647f9f REORG: listener: move the receiving FD to struct receiver
The listening socket is represented by its file descriptor, which is
generic to all receivers and not just listeners, so it must move to
the rx struct.

It's worth noting that in order to extend receivers and listeners to
other protocols such as QUIC, we'll need other handles than file
descriptors here, and that either a union or a cast to uintptr_t
will have to be used. This was not done yet and the field was
preserved under the name "fd" to avoid adding confusion.
2020-09-16 22:08:03 +02:00
Willy Tarreau
371590661e REORG: listener: move the listening address to a struct receiver
The address will be specific to the receiver so let's move it there.
2020-09-16 22:08:01 +02:00
Willy Tarreau
be56c1038f MINOR: listener: move the network namespace to the struct settings
The netns is common to all listeners/receivers and is used to bind the
listening socket so it must be in the receiver settings and not in the
listener. This removes some yet another set of unnecessary loops.
2020-09-16 20:13:13 +02:00
Willy Tarreau
7e307215e8 MINOR: listener: move the interface to the struct settings
The interface is common to all listeners/receivers and is used to bind
the listening socket so it must be in the receiver settings and not in
the listener. This removes some unnecessary loops.
2020-09-16 20:13:13 +02:00
Willy Tarreau
e26993c098 MINOR: listener: move bind_proc and bind_thread to struct settings
As mentioned previously, these two fields come under the settings
struct since they'll be used to bind receivers as well.
2020-09-16 20:13:13 +02:00
Willy Tarreau
6e459d7f92 MINOR: listener: create a new struct "settings" in bind_conf
There currently is a large inconsistency in how binding parameters are
split between bind_conf and listeners. It happens that for historical
reasons some parameters are available at the listener level but cannot
be configured per-listener but only for a bind_conf, and thus, need to
be replicated. In addition, some of the bind_conf parameters are in fact
for the listening socket itself while others are for the instanciated
sockets.

A previous attempt at splitting listeners into receivers failed because
the boundary between all these settings is not well defined.

This patch introduces a level of listening socket settings in the
bind_conf, that will be detachable later. Such settings that are solely
for the listening socket are:
  - unix socket permissions (used only during binding)
  - interface (used for binding)
  - network namespace (used for binding)
  - process mask and thread mask (used during startup)

The rest seems to be used only to initialize the resulting sockets, or
to control the accept rate. For now, only the unix params (bind_conf->ux)
were moved there.
2020-09-16 20:13:13 +02:00
Willy Tarreau
e42d87f3de BUG/MINOR: dns: gracefully handle the "udp@" address format for nameservers
Just like with previous commit, DNS nameservers are affected as well with
addresses starting in "udp@", but here it's different, because due to
another bug in the DNS parser, the address is rejected, indicating that
it doesn't have a ->connect() method. Similarly, the DNS code believes
it's working on top of TCP at this point and this used to work because of
this. The same fix is applied to remap the protocol and the ->connect test
was dropped.

No backport is needed, as the ->connect() test will never strike in 2.2
or below.
2020-09-16 20:11:52 +02:00
Willy Tarreau
e1c4c80441 BUG/MINOR: log: gracefully handle the "udp@" address format for log servers
Commit 3835c0dcb ("MEDIUM: udp: adds minimal proto udp support for
message listeners.") introduced a problematic side effect in log server
address parser: if "udp@", "udp4@" or "udp6@" prefixes a log server's
address, the adress is passed as-is to the log server with a non-existing
family and fails like this when trying to send:

  [ALERT] 259/195708 (3474) : socket() failed in logger #1: Address family not supported by protocol (errno=97)

The problem is that till now there was no UDP family, so logs expect an
AF_INET family to be passed for UDP there.

This patch manually remaps AF_CUST_UDP4 and AF_CUST_UDP6 to their "tcp"
equivalent that the log server parser expects. No backport is needed.
2020-09-16 20:11:52 +02:00
William Lallemand
70bf06e5f0 BUILD: fix build with openssl < 1.0.2 since bundle removal
Bundle removal broke the build with openssl version < 1.0.2.

Remove the #ifdef around SSL_SOCK_KEYTYPE_NAMES.
2020-09-16 18:10:00 +02:00
William Lallemand
e7eb1fec2f CLEANUP: ssl: remove utility functions for bundle
Remove the last utility functions for handling the multi-cert bundles
and remove the multi-variable from the ckch structure.

With this patch, the bundles are completely removed.
2020-09-16 16:28:26 +02:00
William Lallemand
5685ccf75e CLEANUP: ssl/cli: remove test on 'multi' variable in CLI functions
The multi variable is not useful anymore since the removal of the
multi-certificates bundle support. It can be removed safely from the CLI
functions and suppose that every ckch contains a single certificate.
2020-09-16 16:28:26 +02:00
William Lallemand
bd8e6eda59 CLEANUP: ssl: remove test on "multi" variable in ckch functions
Since the removal of the multi-certificates bundle support, this
variable is not useful anymore, we can remove all tests for this
variable and suppose that every ckch contains a single certificate.
2020-09-16 16:28:26 +02:00
William Lallemand
dfa93be3b5 MEDIUM: ssl: emulate multi-cert bundles loading in standard loading
Like the previous commit, this one emulates the bundling by loading each
certificate separately and storing it in a separate SSL_CTX.
This patch does it for the standard certificate loading, which means
outside directories or crt-list.

The multi-certificates bundle was the common way of offering multiple
certificates of different types (ecdsa and rsa) for a same SSL_CTX.
This was implemented with OpenSSL 1.0.2 before the client_hello callback
was available.

Now that all versions which does not support this callback are
deprecated (< 1.1.0), we can safely removes the support for the bundle
which was inconvenient and complexify too much the code.
2020-09-16 16:28:26 +02:00
William Lallemand
47da82111d MEDIUM: ssl: emulates the multi-cert bundles in the crtlist
The multi-certificates bundle was the common way of offering multiple
certificates of different types (ecdsa and rsa) for a same SSL_CTX.
This was implemented with OpenSSL 1.0.2 before the client_hello callback
was available.

Now that all versions which does not support this callback are
depracated (< 1.1.0), we can safely removes the support for the bundle
which was inconvenient and complexify too much the code.

This patch emulates the bundle loading by looking for the bundle files
when the specified file in the configuration does not exist. It then
creates new entries in the crtlist, so they will appear as new line if
they are dumped from the CLI.
2020-09-16 16:28:26 +02:00
William Lallemand
5622c45df4 MINOR: ssl: crtlist_entry_dup() duplicates a crtlist_entry
Implement crtlist_entry_dup() which allocate and duplicate a
crtlist_entry structure.
2020-09-16 16:28:26 +02:00
William Lallemand
82f2d2f1d0 MINOR: ssl: crtlist_dup_ssl_conf() duplicates a ssl_bind_conf
Implement the crtlist_dup_ssl_conf() which allocates and duplicates a
ssl_bind_conf structure.
2020-09-16 16:28:26 +02:00
William Lallemand
95fefa1c09 MEDIUM: ssl/cli: remove support for multi certificates bundle
Remove the support for multi-certificates bundle in the CLI. There is
nothing to replace here, it will use the standard codepath with the
"bundle emulation" in the future.
2020-09-16 16:28:26 +02:00
William Lallemand
89d3b355ad MEDIUM: ssl: remove bundle support in crt-list and directories
The multi-cert certificates bundle is the former way, implemented with
openssl 1.0.2, of doing multi-certificate (RSA, ECDSA and DSA) for the
same SNI host. Remove this support temporarely so it is replaced by
the loading of each certificate in a separate SSL_CTX.
2020-09-16 16:28:26 +02:00
Willy Tarreau
3b139e540a BUG/MEDIUM: log-forward: always quit on parsing errors
The err_code and goto were misplaced, causing a fatal parse error to be
ignored when parsing a UDP listener's address. No backport is needed.
2020-09-16 16:25:29 +02:00
Willy Tarreau
76aaa7f5b7 MEDIUM: log-forward: use "dgram-bind" instead of "bind" for the listener
The use of "bind" wasn't that wise but was temporary. The problem is that
it will not allow to coexist with tcp. Let's explicitly call it "dgram-bind"
so that datagram listeners are expected here, leaving some room for stream
listeners later. This is the only change.
2020-09-16 15:07:22 +02:00
Willy Tarreau
f9feec2813 BUG/MINOR: log-forward: fail on unknown keywords
The log-forward section silently ignores junk and unknown keywords, make
it fail! No backport is needed.
2020-09-16 15:04:33 +02:00
William Lallemand
0354b658f0 BUG/MINOR: ssl/crt-list: crt-list could end without a \n
Since the refactoring of the crt-list, the same function is used to
parse a crt-list file and a crt-list line on the CLI.

The assumption that a line on the CLI and a line in a file is finished
by a \n was made. However that is potentialy not the case with a file
which does not finish by a \n.

This patch fixes issue #860 and must be backported in 2.2.
2020-09-16 11:55:09 +02:00
Olivier Houchard
a459826056 BUG/MEDIUM: ssl: Don't call ssl_sock_io_cb() directly.
In the SSL code, when we were waiting for the availability of the crypto
engine, once it is ready and its fd's I/O handler is called, don't call
ssl_sock_io_cb() directly, instead, call tasklet_wakeup() on the
ssl_sock_ctx's tasklet. We were calling ssl_sock_io_cb() with NULL as
a tasklet, which used to be fine, but it is no longer true since the
fd takeover changes. We could just provide the tasklet, but let's just
wake the tasklet, as is done for other FDs, for fairness.

This should fix github issue #856.

This should be backported into 2.2.
2020-09-15 22:16:02 +02:00
Willy Tarreau
9743f709d0 BUG/MINOR: server: report correct error message for invalid port on "socks4"
The socks4 keyword parser was a bit too much copy-pasted, it only checks
for a null port and reports "invalid range". Let's properly check for the
1-65535 range and report the correct error.

It may be backported everywhere "socks4" is present (2.0).
2020-09-15 12:00:29 +02:00
William Lallemand
2d6fd0a90d BUG/MINOR: ssl: verifyhost is case sensitive
In bug #835, @arjenzorgdoc reported that the verifyhost option on the
server line is case-sensitive, that shouldn't be the case.

This patch fixes the issue by replacing memcmp by strncasecmp and strcmp
by strcasecmp. The patch was suggested by @arjenzorgdoc.

This must be backported in all versions supporting the verifyhost
option.
2020-09-14 15:20:10 +02:00
Tim Duesterhus
e52b6e5456 CLEANUP: Do not use a fixed type for 'sizeof' in 'calloc'
Changes performed using the following coccinelle patch:

    @@
    type T;
    expression E;
    expression t;
    @@

    (
      t = calloc(E, sizeof(*t))
    |
    - t = calloc(E, sizeof(T))
    + t = calloc(E, sizeof(*t))
    )

Looking through the commit history, grepping for coccinelle shows that the same
replacement with a different patch was already performed in the past in commit
02779b6263.
2020-09-12 20:31:25 +02:00
Tim Duesterhus
b53dd03dc0 BUG/MINOR: Fix type passed of sizeof() for calloc()
newsrv->curr_idle_thr is of type `unsigned int`, not `int`. Fix this issue
by simply passing the dereferenced pointer to sizeof, which is the preferred
style anyway.

This bug was introduced in commit dc2f2753e9.
It first appeared in 2.2-dev5. The patch must be backported to 2.2+.

It is notable that the `calloc` call was not introduced within the commit in
question. The allocation was already happening before that commit and it
already looked like it does after applying the patch. Apparently the
argument for the `sizeof` managed to get broken during the rearrangement
that happened in that commit:

     	for (i = 0; i < global.nbthread; i++)
    -		MT_LIST_INIT(&newsrv->idle_orphan_conns[i]);
    -	newsrv->curr_idle_thr = calloc(global.nbthread, sizeof(*newsrv->curr_idle_thr));
    +		MT_LIST_INIT(&newsrv->safe_conns[i]);
    +
    +	newsrv->curr_idle_thr = calloc(global.nbthread, sizeof(int));

Even more notable is that I previously fixed that *exact same* allocation in
commit 017484c80f.

So apparently it was managed to break this single line twice in the same
way for whatever reason there might be.
2020-09-12 20:31:25 +02:00
Tim Duesterhus
3943e4fc3e MINOR: sample: Add iif(<true>,<false>) converter
iif() takes a boolean as input and returns one of the two argument
strings depending on whether the boolean is true.

This converter most likely is most useful to return the proper scheme
depending on the value returned by the `ssl_fc` fetch, e.g. for use within
the `x-forwarded-proto` request header.

However it can also be useful for use within a template that is sent to
the client using `http-request return` with a `lf-file`. It allows the
administrator to implement a simple condition, without needing to prefill
variables within the regular configuration using `http-request
set-var(req.foo)`.
2020-09-11 16:59:27 +02:00
Christopher Faulet
6cfc851674 BUG/MEDIUM: pattern: Renew the pattern expression revision when it is pruned
It must be done to expire patterns cached in the LRU cache. Otherwise it is
possible to retrieve an already freed pattern, attached to a released pattern
expression.

When a specific pattern is deleted (->delete() callback), the pattern expression
revision is already renewed. Thus it is not affected by this bug. Only prune
action on the pattern expression is concerned.

In addition, for a pattern expression, in ->prune() callbacks when the pattern
list is released, a missing LIST_DEL() has been added. It is not a real issue
because the list is reinitialized at the end and all elements are released and
should never be reused. But it is less confusing this way.

This bug may be triggered when a map is cleared from the cli socket. A
workaround is to set the pattern cache size (tune.pattern.cache-size) to 0 to
disable it.

This patch should fix the issue #844. It must be backported to all supported
versions.
2020-09-11 09:54:34 +02:00
Tim Duesterhus
fc85494c99 CLEANUP: haproxy: Free post_check_list in deinit()
This allocation is technically always reachable and cannot leak, but so are
a few others that *are* freed.
2020-09-11 07:54:39 +02:00
Tim Duesterhus
f0c25d210c CLEANUP: haproxy: Free per_thread_*_list in deinit()
This allocation is technically always reachable and cannot leak, but so are
a few others that *are* freed.
2020-09-11 07:54:39 +02:00
Tim Duesterhus
53508d6564 CLEANUP: haproxy: Free post_proxy_check_list in deinit()
This allocation is technically always reachable and cannot leak, but so are
a few others that *are* freed.
2020-09-11 07:54:39 +02:00
Tim Duesterhus
9e0c2f34dc CLEANUP: Free old_argv on deinit
This allocation technically is always reachable and cannot leak, however other
global variables such as `oldpids` are already being freed. This is in an
attempt to get HAProxy to a state where there are zero live allocations after a
clean exit.
2020-09-11 07:54:39 +02:00
Tim Duesterhus
00f00cf8fd BUG/MINOR: haproxy: Free uri_auth->scope during deinit
Given the following example configuration:

    listen http
    	bind *:80
    	mode http
    	stats scope .

Running a configuration check with valgrind reports:

    ==16341== 26 (24 direct, 2 indirect) bytes in 1 blocks are definitely lost in loss record 3 of 13
    ==16341==    at 0x4C2FB55: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==16341==    by 0x571C2E: stats_add_scope (uri_auth.c:296)
    ==16341==    by 0x46CE29: cfg_parse_listen (cfgparse-listen.c:1901)
    ==16341==    by 0x45A112: readcfgfile (cfgparse.c:2078)
    ==16341==    by 0x50A0F5: init (haproxy.c:1828)
    ==16341==    by 0x418248: main (haproxy.c:3012)

After this patch is applied the leak is gone as expected.

This is a very minor leak that can only be observed if deinit() is called,
shortly before the OS will free all memory of the process anyway. No
backport needed.
2020-09-11 07:54:39 +02:00
Willy Tarreau
022e5e56ed BUILD: traces: don't pass an empty argument for missing ones
It initially looked appealing to be able to call traces with ",,," for
unused arguments, but tcc doesn't like empty macro arguments, and quite
frankly, adding a zero between the few remaining ones is no big deal.
Let's do so now.
2020-09-10 09:37:52 +02:00
Willy Tarreau
f734ebfac4 BUILD: threads: better workaround for late loading of libgcc_s
Commit 77b98220e ("BUG/MINOR: threads: work around a libgcc_s issue with
chrooting") tried to address an issue with libgcc_s being loaded too late.
But it turns out that the symbol used there isn't present on armhf, thus
it breaks the build.

Given that the issue manifests itself during pthread_exit(), the safest
and most portable way to test this is to call pthread_exit(). For this
we create a dummy thread which exits, during the early boot. This results
in the relevant library to be loaded if needed, making sure that a later
call to pthread_exit() will still work. It was tested to work fine under
linux on the following platforms:

 glibc:
   - armhf
   - aarch64
   - x86_64
   - sparc64
   - ppc64le

 musl:
   - mipsel

Just running the code under strace easily shows the call in the dummy
thread, for example here on armhf:

  $ strace -fe trace=file ./haproxy -v 2>&1 | grep gcc_s
  [pid 23055] open("/lib/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = 3

The code was isolated so that it's easy to #ifdef it out if needed.
This should be backported where the patch above is backported (likely
2.0).
2020-09-09 19:10:46 +02:00
Willy Tarreau
4313d5ae98 BUG/MEDIUM: mux-h1: always apply the timeout on half-closed connections
The condition in h1_refresh_timeout() seems insufficient to properly
take care of the half-closed timeout, because depending on the ordering
of operations when performing the last send() to a client, the stream
may or may not still be there and we may fail to shrink the client
timeout on our last opportunity to do so.

Here we want to make sure that the timeout is always reduced when the
last chunk was sent and the shutdown completed, regardless of the
presence of a stream or not. This is what this patch does.

This should be backported as far as 2.0, and should fix the issue
reported in #541.
2020-09-08 15:49:40 +02:00
Victor Kislov
ec00251c88 BUG/MINOR: auth: report valid crypto(3) support depending on build options
Since 1.8 with commit e8692b41e ("CLEANUP: auth: use the build options list
to report its support"), crypt(3) is always reported as being supported in
"haproxy -vv" because no test on USE_LIBCRYPT is made anymore when
producing the output.

This reintroduces the distinction between with and without USE_LIBCRYPT
in the output by indicating "yes" or "no". It may be backported as far
as 1.8, though the code differs due to a number of include files cleanups.
2020-09-08 14:34:04 +02:00
Christopher Faulet
b0b7607a54 MINOR: server: Improve log message sent when server address is updated
When the server address is set for the first time, the log message is a bit ugly
because there is no old ip address to report. Thus in the log, we can see :

  PX/SRV changed its IP from  to A.B.C.D by DNS additional record.

Now, when this happens, "(none)" is reported :

  PX/SRV changed its IP from (none) to A.B.C.D by DNS additional record.

This patch may be backported to 2.2.
2020-09-08 10:44:57 +02:00
Christopher Faulet
d6c6b5f43b BUG/MEDIUM: dns: Be sure to renew IP address for already known servers
When a SRV record for an already known server is processed, only the weight is
updated, if not configured to be ignored. It is a problem if the IP address
carried by the associated additional record changes. Because the server IP
address is never renewed.

To fix this bug, If there is an addition record attached to a SRV record, we
always try to set the IP address. If it is the same, no change is
performed. This way, IP changes are always handled.

This patch should fix the issue #841. It must be backported to 2.2.
2020-09-08 10:44:57 +02:00