]> git.ipfire.org Git - thirdparty/haproxy.git/log
thirdparty/haproxy.git
4 years agoMINOR: tools: make str2sa_range() directly return the protocol
Willy Tarreau [Wed, 16 Sep 2020 16:25:03 +0000 (18:25 +0200)] 
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

4 years agoMINOR: listener: pass the chosen protocol to create_listeners()
Willy Tarreau [Wed, 16 Sep 2020 15:58:55 +0000 (17:58 +0200)] 
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.

4 years agoMEDIUM: config: make str2listener() not accept datagram sockets anymore
Willy Tarreau [Wed, 16 Sep 2020 14:28:08 +0000 (16:28 +0200)] 
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.

4 years agoMINOR: log-forward: use str2receiver() to parse the dgram-bind address
Willy Tarreau [Wed, 16 Sep 2020 13:22:19 +0000 (15:22 +0200)] 
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.

4 years agoMINOR: cfgparse: add str2receiver() to parse dgram receivers
Willy Tarreau [Wed, 16 Sep 2020 13:13:04 +0000 (15:13 +0200)] 
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.

4 years agoMINOR: tools: remove the central test for "udp" in str2sa_range()
Willy Tarreau [Wed, 16 Sep 2020 13:20:59 +0000 (15:20 +0200)] 
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.

4 years agoMEDIUM: tools: make str2sa_range() only report AF_CUST_UDP on listeners
Willy Tarreau [Wed, 16 Sep 2020 18:35:12 +0000 (20:35 +0200)] 
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.

4 years agoMINOR: tools: start to distinguish stream and dgram in str2sa_range()
Willy Tarreau [Wed, 16 Sep 2020 09:35:47 +0000 (11:35 +0200)] 
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".

4 years agoMEDIUM: tools: make str2sa_range() check for the sockpair's FD usability
Willy Tarreau [Wed, 16 Sep 2020 08:14:16 +0000 (10:14 +0200)] 
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).

4 years agoMINOR: config: do not test an inherited socket again
Willy Tarreau [Wed, 16 Sep 2020 08:43:38 +0000 (10:43 +0200)] 
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().

4 years agoMEDIUM: tools: make str2sa_range() resolve pre-bound listeners
Willy Tarreau [Tue, 15 Sep 2020 15:41:56 +0000 (17:41 +0200)] 
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).

4 years agoMINOR: log: detect LOG_TARGET_FD from the fd and not from the syntax
Willy Tarreau [Tue, 15 Sep 2020 12:03:26 +0000 (14:03 +0200)] 
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.

4 years agoMINOR: tools: make str2sa_range() optionally return the fd
Willy Tarreau [Tue, 15 Sep 2020 12:01:16 +0000 (14:01 +0200)] 
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.

4 years agoMINOR: listener: remove the inherited arg to create_listener()
Willy Tarreau [Tue, 15 Sep 2020 11:50:58 +0000 (13:50 +0200)] 
MINOR: listener: remove the inherited arg to create_listener()

This argument can now safely be determined from fd != -1, let's just
drop it.

4 years agoMINOR: tools: add several PA_O_* flags in str2sa_range() callers
Willy Tarreau [Fri, 4 Sep 2020 13:53:16 +0000 (15:53 +0200)] 
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.

4 years agoMEDIUM: config: remove all checks for missing/invalid ports/ranges
Willy Tarreau [Tue, 15 Sep 2020 09:52:23 +0000 (11:52 +0200)] 
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.

4 years agoMEDIUM: tools: make str2sa_range() validate callers' port specifications
Willy Tarreau [Tue, 15 Sep 2020 09:12:44 +0000 (11:12 +0200)] 
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.

4 years agoMINOR: tools: add several PA_O_PORT_* flags in str2sa_range() callers
Willy Tarreau [Tue, 15 Sep 2020 08:30:39 +0000 (10:30 +0200)] 
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.

4 years agoMINOR: tools: make str2sa_range() take more options than just resolve
Willy Tarreau [Fri, 4 Sep 2020 13:30:46 +0000 (15:30 +0200)] 
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.

4 years agoCLEANUP: tools: make str2sa_range() less awful for fd@ and sockpair@
Willy Tarreau [Fri, 4 Sep 2020 14:54:05 +0000 (16:54 +0200)] 
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.

4 years agoMINOR: protocol: add a real family for existing FDs
Willy Tarreau [Fri, 4 Sep 2020 14:44:20 +0000 (16:44 +0200)] 
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.

4 years agoCLEANUP: protocol: remove family-specific fields from struct protocol
Willy Tarreau [Fri, 4 Sep 2020 06:23:14 +0000 (08:23 +0200)] 
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.

4 years agoMINOR: protocol: retrieve the family-specific fields from the family
Willy Tarreau [Fri, 4 Sep 2020 06:15:31 +0000 (08:15 +0200)] 
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.

4 years agoMINOR: protocol: add a new proto_fam structure for protocol families
Willy Tarreau [Fri, 4 Sep 2020 06:07:11 +0000 (08:07 +0200)] 
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.

4 years agoMEDIUM: protocol: do not call proto->bind() anymore from bind_listener()
Willy Tarreau [Wed, 2 Sep 2020 16:40:02 +0000 (18:40 +0200)] 
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!

4 years agoMEDIUM: protocol: explicitly start the receiver before the listener
Willy Tarreau [Wed, 2 Sep 2020 16:22:11 +0000 (18:22 +0200)] 
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.

4 years agoMEDIUM: proto_sockpair: make use of sockpair_bind_receiver()
Willy Tarreau [Wed, 2 Sep 2020 16:02:00 +0000 (18:02 +0200)] 
MEDIUM: proto_sockpair: make use of sockpair_bind_receiver()

Now we rely on the address family's receiver instead of binding everything
ourselves.

4 years agoMEDIUM: sockpair: implement sockpair_bind_receiver()
Willy Tarreau [Wed, 2 Sep 2020 15:52:23 +0000 (17:52 +0200)] 
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.

4 years agoMEDIUM: uxst: make use of sock_unix_bind_receiver()
Willy Tarreau [Wed, 2 Sep 2020 15:21:02 +0000 (17:21 +0200)] 
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.

4 years agoMEDIUM: sock_unix: implement sock_unix_bind_receiver()
Willy Tarreau [Wed, 2 Sep 2020 15:14:29 +0000 (17:14 +0200)] 
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().

4 years agoMEDIUM: udp: make use of sock_inet_bind_receiver()
Willy Tarreau [Tue, 1 Sep 2020 14:23:29 +0000 (16:23 +0200)] 
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().

4 years agoMEDIUM: tcp: make use of sock_inet_bind_receiver()
Willy Tarreau [Tue, 1 Sep 2020 14:12:50 +0000 (16:12 +0200)] 
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.

4 years agoMEDIUM: sock_inet: implement sock_inet_bind_receiver()
Willy Tarreau [Tue, 1 Sep 2020 12:18:04 +0000 (14:18 +0200)] 
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().

4 years agoMINOR: protocol: add a new ->bind() entry to bind the receiver
Willy Tarreau [Wed, 2 Sep 2020 11:48:45 +0000 (13:48 +0200)] 
MINOR: protocol: add a new ->bind() entry to bind the receiver

This will be the function that must be used to bind the receiver. It
solely depends on the address family but for now it's simpler to have
it per protocol.

4 years agoMINOR: protocol: rename the ->bind field to ->listen
Willy Tarreau [Tue, 1 Sep 2020 08:26:22 +0000 (10:26 +0200)] 
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.

4 years agoMINOR: sock: make sock_find_compatible_fd() only take a receiver
Willy Tarreau [Tue, 1 Sep 2020 13:20:52 +0000 (15:20 +0200)] 
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.

4 years agoMINOR: receiver: move the FOREIGN and V6ONLY options from listener to settings
Willy Tarreau [Tue, 1 Sep 2020 13:12:08 +0000 (15:12 +0200)] 
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.

4 years agoMINOR: listener: move the INHERITED flag down to the receiver
Willy Tarreau [Tue, 1 Sep 2020 13:41:59 +0000 (15:41 +0200)] 
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.

4 years agoMINOR: receiver: add a receiver-specific flag to indicate the socket is bound
Willy Tarreau [Tue, 1 Sep 2020 08:47:07 +0000 (10:47 +0200)] 
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.

4 years agoMINOR: listener: prefer to retrieve the socket's settings via the receiver
Willy Tarreau [Thu, 3 Sep 2020 05:50:19 +0000 (07:50 +0200)] 
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.

4 years agoMINOR: receiver: link the receiver to its owner
Willy Tarreau [Thu, 3 Sep 2020 08:05:03 +0000 (10:05 +0200)] 
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.

4 years agoMINOR: receiver: link the receiver to its settings
Willy Tarreau [Thu, 3 Sep 2020 05:46:06 +0000 (07:46 +0200)] 
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.

4 years agoREORG: listener: move the receiver part to a new file
Willy Tarreau [Tue, 1 Sep 2020 08:37:19 +0000 (10:37 +0200)] 
REORG: listener: move the receiver part to a new file

We'll soon add flags for the receivers, better add them to the final
file, so it's time to move the definition to receiver-t.h. The struct
receiver and rx_settings were placed there.

4 years agoMINOR: listener: make sock_find_compatible_fd() check the socket type
Willy Tarreau [Wed, 16 Sep 2020 19:44:42 +0000 (21:44 +0200)] 
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.

4 years agoREORG: listener: move the listener's proto to the receiver
Willy Tarreau [Fri, 28 Aug 2020 17:51:44 +0000 (19:51 +0200)] 
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.

4 years agoREORG: listener: move the receiving FD to struct receiver
Willy Tarreau [Thu, 27 Aug 2020 06:16:52 +0000 (08:16 +0200)] 
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.

4 years agoREORG: listener: move the listening address to a struct receiver
Willy Tarreau [Thu, 27 Aug 2020 05:48:42 +0000 (07:48 +0200)] 
REORG: listener: move the listening address to a struct receiver

The address will be specific to the receiver so let's move it there.

4 years agoREORG: listener: create a new struct receiver
Willy Tarreau [Thu, 27 Aug 2020 05:48:42 +0000 (07:48 +0200)] 
REORG: listener: create a new struct receiver

In order to start to split the listeners into the listener part and the
event receiver part, we introduce a new field "rx" into struct listener
that will eventually become a separate struct receiver. This patch only
adds the struct with an options field that the receivers will need.

4 years agoMINOR: listener: move the network namespace to the struct settings
Willy Tarreau [Thu, 3 Sep 2020 05:27:34 +0000 (07:27 +0200)] 
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.

4 years agoMINOR: listener: move the interface to the struct settings
Willy Tarreau [Thu, 3 Sep 2020 05:23:34 +0000 (07:23 +0200)] 
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.

4 years agoMINOR: listener: move bind_proc and bind_thread to struct settings
Willy Tarreau [Thu, 3 Sep 2020 05:18:55 +0000 (07:18 +0200)] 
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.

4 years agoMINOR: listener: create a new struct "settings" in bind_conf
Willy Tarreau [Thu, 3 Sep 2020 05:09:09 +0000 (07:09 +0200)] 
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.

4 years agoBUG/MINOR: dns: gracefully handle the "udp@" address format for nameservers
Willy Tarreau [Wed, 16 Sep 2020 18:04:17 +0000 (20:04 +0200)] 
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.

4 years agoBUG/MINOR: log: gracefully handle the "udp@" address format for log servers
Willy Tarreau [Wed, 16 Sep 2020 17:58:34 +0000 (19:58 +0200)] 
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.

4 years agoBUILD: fix build with openssl < 1.0.2 since bundle removal
William Lallemand [Wed, 16 Sep 2020 16:08:14 +0000 (18:08 +0200)] 
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.

4 years agoDOC: explain bundle emulation in configuration.txt
William Lallemand [Wed, 16 Sep 2020 15:42:37 +0000 (17:42 +0200)] 
DOC: explain bundle emulation in configuration.txt

HAProxy 2.3 does not support OpenSSL 1.0.2 bundle anymore, and requires
OpenSSL 1.1.1 to do serve multiple certificate types with the same SNI.

4 years agoCLEANUP: ssl: remove utility functions for bundle
William Lallemand [Wed, 16 Sep 2020 14:17:51 +0000 (16:17 +0200)] 
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.

4 years agoCLEANUP: ssl/cli: remove test on 'multi' variable in CLI functions
William Lallemand [Wed, 16 Sep 2020 14:12:25 +0000 (16:12 +0200)] 
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.

4 years agoCLEANUP: ssl: remove test on "multi" variable in ckch functions
William Lallemand [Wed, 16 Sep 2020 14:08:08 +0000 (16:08 +0200)] 
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.

4 years agoMEDIUM: ssl: emulate multi-cert bundles loading in standard loading
William Lallemand [Wed, 16 Sep 2020 12:48:52 +0000 (14:48 +0200)] 
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.

4 years agoMEDIUM: ssl: emulates the multi-cert bundles in the crtlist
William Lallemand [Thu, 10 Sep 2020 17:13:27 +0000 (19:13 +0200)] 
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.

4 years agoMINOR: ssl: crtlist_entry_dup() duplicates a crtlist_entry
William Lallemand [Thu, 10 Sep 2020 17:08:49 +0000 (19:08 +0200)] 
MINOR: ssl: crtlist_entry_dup() duplicates a crtlist_entry

Implement crtlist_entry_dup() which allocate and duplicate a
crtlist_entry structure.

4 years agoMINOR: ssl: crtlist_dup_ssl_conf() duplicates a ssl_bind_conf
William Lallemand [Thu, 10 Sep 2020 17:06:43 +0000 (19:06 +0200)] 
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.

4 years agoMEDIUM: ssl/cli: remove support for multi certificates bundle
William Lallemand [Wed, 9 Sep 2020 10:01:33 +0000 (12:01 +0200)] 
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.

4 years agoMEDIUM: ssl: remove bundle support in crt-list and directories
William Lallemand [Wed, 9 Sep 2020 09:42:04 +0000 (11:42 +0200)] 
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.

4 years agoBUG/MEDIUM: log-forward: always quit on parsing errors
Willy Tarreau [Wed, 16 Sep 2020 14:24:14 +0000 (16:24 +0200)] 
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.

4 years agoMEDIUM: log-forward: use "dgram-bind" instead of "bind" for the listener
Willy Tarreau [Wed, 16 Sep 2020 13:07:22 +0000 (15:07 +0200)] 
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.

4 years agoBUG/MINOR: log-forward: fail on unknown keywords
Willy Tarreau [Wed, 16 Sep 2020 13:04:33 +0000 (15:04 +0200)] 
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.

4 years agoBUG/MINOR: ssl/crt-list: crt-list could end without a \n
William Lallemand [Wed, 16 Sep 2020 09:55:09 +0000 (11:55 +0200)] 
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.

4 years agoBUG/MEDIUM: ssl: Don't call ssl_sock_io_cb() directly.
Olivier Houchard [Tue, 15 Sep 2020 20:16:02 +0000 (22:16 +0200)] 
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.

4 years agoBUG/MINOR: server: report correct error message for invalid port on "socks4"
Willy Tarreau [Tue, 15 Sep 2020 09:25:54 +0000 (11:25 +0200)] 
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).

4 years agoCI: travis-ci: split asan step out of running tests
Ilya Shipitsin [Thu, 27 Aug 2020 16:00:09 +0000 (21:00 +0500)] 
CI: travis-ci: split asan step out of running tests

when asan (address sanitizer) is enabled, it's findings were mixed
with test debug output and it was hard to identify whether tests
failed or asan failed.

let us output asan log to separate file and report its findings
separately

4 years agoBUILD: makefile: change default value of CC from gcc to cc
Brad Smith [Sun, 13 Sep 2020 06:53:06 +0000 (02:53 -0400)] 
BUILD: makefile: change default value of CC from gcc to cc

Change the default value of CC from gcc to cc to be more appropriate
for modern day mix of compilers. On GCC based OS's cc -> gcc. On Clang
based OS's cc -> clang. FreeBSD / OpenBSD have switched to Clang and
this corrects building with the proper compiler on OS's using Clang
as the default compiler. This especially matters for the necessity for
TLS on OpenBSD. I would expect this affects OpenMandriva and other
Linux OS's using Clang as well.

4 years agoBUG/MINOR: ssl: verifyhost is case sensitive
William Lallemand [Mon, 14 Sep 2020 13:20:10 +0000 (15:20 +0200)] 
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.

4 years agoBUILD: connection: fix build on clang after the VAR_ARRAY cleanup
Willy Tarreau [Mon, 14 Sep 2020 06:43:51 +0000 (08:43 +0200)] 
BUILD: connection: fix build on clang after the VAR_ARRAY cleanup

Commit 4987a4744 ("CLEANUP: tree-wide: use VAR_ARRAY instead of [0] in
various definitions") broke the build on clang due to the tlv field used
to receive/send the proxy protocol. The problem is that struct tlv is
included at the beginning of struct tlv_ssl, which doesn't make much
sense. In fact the value[] array isn't really a var array but just an
end of struct marker, and must really be an array of size zero.

4 years agoCLEANUP: tree-wide: use VAR_ARRAY instead of [0] in various definitions
Willy Tarreau [Sat, 12 Sep 2020 18:56:41 +0000 (20:56 +0200)] 
CLEANUP: tree-wide: use VAR_ARRAY instead of [0] in various definitions

Surprisingly there were still a number of [0] definitions for variable
sized arrays in certain structures all over the code. We need to use
VAR_ARRAY instead of zero to accommodate various compilers' preferences,
as zero was used only on old ones and tends to report errors on new ones.

4 years agoCLEANUP: Do not use a fixed type for 'sizeof' in 'calloc'
Tim Duesterhus [Sat, 12 Sep 2020 18:26:43 +0000 (20:26 +0200)] 
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
02779b6263a177b1e462e53db6eaf57bcda574bc.

4 years agoBUG/MINOR: Fix type passed of sizeof() for calloc()
Tim Duesterhus [Sat, 12 Sep 2020 18:26:42 +0000 (20:26 +0200)] 
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 dc2f2753e97ecfe94827de56ee9efd2cd6d39ad3.
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 017484c80f2fd265281853fdf0bc816b19a751da.

So apparently it was managed to break this single line twice in the same
way for whatever reason there might be.

4 years agoCI: travis-ci: help Coverity to recognize abort()
Ilya Shipitsin [Sat, 12 Sep 2020 06:27:51 +0000 (11:27 +0500)] 
CI: travis-ci: help Coverity to recognize abort()

generally haproxy uses (*(volatile int*)1=0) for abort. It is not recognized
by static analyzers, e.g. Coverity scan as abort, so fallback to abort() was
introduced in previous commit for code analysis purpose. Let us explicitely
use it for Coverity build job

4 years agoBUILD: introduce possibility to define ABORT_NOW() conditionally
Ilya Shipitsin [Sat, 12 Sep 2020 06:24:48 +0000 (11:24 +0500)] 
BUILD: introduce possibility to define ABORT_NOW() conditionally

code analysis tools recognize abort() better, so let us introduce
such possibility

4 years agoCLEANUP: Update .gitignore
Ilya Shipitsin [Sat, 12 Sep 2020 06:15:43 +0000 (11:15 +0500)] 
CLEANUP: Update .gitignore

This excludes ar archives from being ignored.

4 years agoDOC: Fix typo in iif() example
Tim Duesterhus [Fri, 11 Sep 2020 15:13:12 +0000 (17:13 +0200)] 
DOC: Fix typo in iif() example

It should read 'iif', not 'iff'.

Reported-by: Miroslav Zagorac <zaga@fly-etf.net>
4 years ago[RELEASE] Released version 2.3-dev4 v2.3-dev4
Willy Tarreau [Fri, 11 Sep 2020 15:05:59 +0000 (17:05 +0200)] 
[RELEASE] Released version 2.3-dev4

Released version 2.3-dev4 with the following main changes :
    - MINOR: hlua: Add error message relative to the Channel manipulation and HTTP mode
    - BUG/MEDIUM: ssl: crt-list negative filters don't work
    - DOC: overhauling github issue templates
    - MEDIUM: cfgparse: Emit hard error on truncated lines
    - DOC: cache: Use '<name>' instead of '<id>' in error message
    - MINOR: cache: Reject duplicate cache names
    - REGTEST: remove stray leading spaces in converteers_ref_cnt_never_dec.vtc
    - MINOR: stats: prevent favicon.ico requests for stats page
    - BUILD: tools: include auxv a bit later
    - BUILD: task: work around a bogus warning in gcc 4.7/4.8 at -O1
    - MEDIUM: ssl: Support certificate chaining for certificate generation
    - MINOR: ssl: Support SAN extension for certificate generation
    - MINOR: tcp: don't try to set/clear v6only on inherited sockets
    - BUG/MINOR: reload: detect the OS's v6only status before choosing an old socket
    - MINOR: reload: determine the foreing binding status from the socket
    - MEDIUM: reload: stop passing listener options along with FDs
    - BUG/MEDIUM: ssl: fix ssl_bind_conf double free w/ wildcards
    - MEDIUM: fd: replace usages of fd_remove() with fd_stop_both()
    - CLEANUP: fd: remove fd_remove() and rename fd_dodelete() to fd_delete()
    - MINOR: fd: add a new "exported" flag and use it for all regular listeners
    - MEDIUM: reload: pass all exportable FDs, not just listeners
    - DOC: add description of pidfile in master-worker mode
    - BUG/MINOR: reload: do not fail when no socket is sent
    - REORG: tcp: move TCP actions from proto_tcp.c to tcp_act.c
    - CLEANUP: tcp: stop exporting smp_fetch_src()
    - REORG: tcp: move TCP sample fetches from proto_tcp.c to tcp_sample.c
    - REORG: tcp: move TCP bind/server keywords from proto_tcp.c to cfgparse-tcp.c
    - REORG: unix: move UNIX bind/server keywords from proto_uxst.c to cfgparse-unix.c
    - REORG: sock: start to move some generic socket code to sock.c
    - MINOR: sock: introduce sock_inet and sock_unix
    - MINOR: tcp/udp/unix: make use of proto->addrcmp() to compare addresses
    - MINOR: sock_inet: implement sock_inet_get_dst()
    - REORG: inet: replace tcp_is_foreign() with sock_inet_is_foreign()
    - REORG: sock_inet: move v6only_default from proto_tcp.c to sock_inet.c
    - REORG: sock_inet: move default_tcp_maxseg from proto_tcp.c
    - REORG: listener: move xfer_sock_list to sock.{c,h}.
    - MINOR: sock: add interface and namespace length to xfer_sock_list
    - MINOR: sock: implement sock_find_compatible_fd()
    - MINOR: sock_inet: move the IPv4/v6 transparent mode code to sock_inet
    - REORG: sock: move get_old_sockets() from haproxy.c
    - MINOR: sock: do not use LI_O_* in xfer_sock_list anymore
    - MINOR: sock: distinguish dgram from stream types when retrieving old sockets
    - BUILD: sock_unix: fix build issue with isdigit()
    - BUG/MEDIUM: http-ana: Don't wait to send 1xx responses received from servers
    - MINOR: http-htx: Add an option to eval query-string when the path is replaced
    - BUG/MINOR: http-rules: Replace path and query-string in "replace-path" action
    - MINOR: http-htx: Handle an optional reason when replacing the response status
    - MINOR: contrib/spoa-server: allow MAX_FRAME_SIZE override
    - BUG/MAJOR: contrib/spoa-server: Fix unhandled python call leading to memory leak
    - BUG/MINOR: contrib/spoa-server: Ensure ip address references are freed
    - BUG/MINOR: contrib/spoa-server: Do not free reference to NULL
    - BUG/MINOR: contrib/spoa-server: Updating references to free in case of failure
    - BUG/MEDIUM: contrib/spoa-server: Fix ipv4_address used instead of ipv6_address
    - CLEANUP: http: silence a cppcheck warning in get_http_auth()
    - REGTEST: increase some short timeouts to make tests more reliable
    - BUG/MINOR: threads: work around a libgcc_s issue with chrooting
    - BUILD: thread: limit the libgcc_s workaround to glibc only
    - MINOR: protocol: do not call proto->bind_all() anymore
    - MINOR: protocol: do not call proto->unbind_all() anymore
    - CLEANUP: protocol: remove all ->bind_all() and ->unbind_all() functions
    - MAJOR: init: start all listeners via protocols and not via proxies anymore
    - BUG/MINOR: startup: haproxy -s cause 100% cpu
    - Revert "BUG/MINOR: http-rules: Replace path and query-string in "replace-path" action"
    - BUG/MEDIUM: doc: Fix replace-path action description
    - MINOR: http-rules: Add set-pathq and replace-pathq actions
    - MINOR: http-fetch: Add pathq sample fetch
    - REGTEST: Add a test for request path manipulations, with and without the QS
    - MINOR: Commit .gitattributes
    - CLEANUP: Update .gitignore
    - BUG/MEDIUM: dns: Don't store additional records in a linked-list
    - BUG/MEDIUM: dns: Be sure to renew IP address for already known servers
    - MINOR: server: Improve log message sent when server address is updated
    - DOC: ssl-load-extra-files only applies to certificates on bind lines
    - BUG/MINOR: auth: report valid crypto(3) support depending on build options
    - BUG/MEDIUM: mux-h1: always apply the timeout on half-closed connections
    - BUILD: threads: better workaround for late loading of libgcc_s
    - BUILD: compiler: reserve the gcc version checks to the gcc compiler
    - BUILD: compiler: workaround a glibc madness around __attribute__()
    - BUILD: intops: on x86_64, the bswap instruction is called bswapq
    - BUILD: trace: always have an argument before variadic args in macros
    - BUILD: traces: don't pass an empty argument for missing ones
    - BUG/MINOR: haproxy: Free uri_auth->scope during deinit
    - CLEANUP: Free old_argv on deinit
    - CLEANUP: haproxy: Free post_proxy_check_list in deinit()
    - CLEANUP: haproxy: Free per_thread_*_list in deinit()
    - CLEANUP: haproxy: Free post_check_list in deinit()
    - BUG/MEDIUM: pattern: Renew the pattern expression revision when it is pruned
    - REORG: tools: move PARSE_OPT_* from tools.h to tools-t.h
    - MINOR: sample: Add iif(<true>,<false>) converter

4 years agoMINOR: sample: Add iif(<true>,<false>) converter
Tim Duesterhus [Fri, 11 Sep 2020 12:25:23 +0000 (14:25 +0200)] 
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)`.

4 years agoREORG: tools: move PARSE_OPT_* from tools.h to tools-t.h
Willy Tarreau [Fri, 4 Sep 2020 13:24:53 +0000 (15:24 +0200)] 
REORG: tools: move PARSE_OPT_* from tools.h to tools-t.h

These would better be placed into the low-level type files with other
similar macros.

4 years agoBUG/MEDIUM: pattern: Renew the pattern expression revision when it is pruned
Christopher Faulet [Wed, 9 Sep 2020 14:09:44 +0000 (16:09 +0200)] 
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.

4 years agoCLEANUP: haproxy: Free post_check_list in deinit()
Tim Duesterhus [Thu, 10 Sep 2020 17:46:42 +0000 (19:46 +0200)] 
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.

4 years agoCLEANUP: haproxy: Free per_thread_*_list in deinit()
Tim Duesterhus [Thu, 10 Sep 2020 17:46:41 +0000 (19:46 +0200)] 
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.

4 years agoCLEANUP: haproxy: Free post_proxy_check_list in deinit()
Tim Duesterhus [Thu, 10 Sep 2020 17:46:40 +0000 (19:46 +0200)] 
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.

4 years agoCLEANUP: Free old_argv on deinit
Tim Duesterhus [Thu, 10 Sep 2020 17:46:39 +0000 (19:46 +0200)] 
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.

4 years agoBUG/MINOR: haproxy: Free uri_auth->scope during deinit
Tim Duesterhus [Thu, 10 Sep 2020 17:46:38 +0000 (19:46 +0200)] 
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.

4 years agoBUILD: traces: don't pass an empty argument for missing ones
Willy Tarreau [Thu, 10 Sep 2020 07:33:15 +0000 (09:33 +0200)] 
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.

4 years agoBUILD: trace: always have an argument before variadic args in macros
Willy Tarreau [Thu, 10 Sep 2020 07:35:54 +0000 (09:35 +0200)] 
BUILD: trace: always have an argument before variadic args in macros

tcc supports variadic macros provided that there is always at least one
argument, like older gcc versions. Thus we need to always keep one and
define args as the remaining ones. It's not an issue at all and doesn't
change the way to use them, just the internal definitions.

4 years agoBUILD: intops: on x86_64, the bswap instruction is called bswapq
Willy Tarreau [Thu, 10 Sep 2020 07:31:50 +0000 (09:31 +0200)] 
BUILD: intops: on x86_64, the bswap instruction is called bswapq

Building with tcc fails on "bswap" which in fact ought to be called
"bswapq". Let's rename it as gas doesn't care.

4 years agoBUILD: compiler: workaround a glibc madness around __attribute__()
Willy Tarreau [Thu, 10 Sep 2020 07:26:50 +0000 (09:26 +0200)] 
BUILD: compiler: workaround a glibc madness around __attribute__()

For whatever reason, glibc decided that the __attribute__ keyword is
the exclusive property of gcc, and redefines it to an empty macro on
other compilers. Some non-gcc compilers also support it (possibly
partially), tinycc is one of them. By doing this, glibc silently
broke all constructors, resulting in code that arrives in main() with
uninitialized variables.

The solution we use here consists in undefining the macro on non-gcc
compilers, and redefining it to itself in order to cause a conflict in
the event the redefinition would happen afterwards. This visibly solved
the problem.

4 years agoBUILD: compiler: reserve the gcc version checks to the gcc compiler
Willy Tarreau [Thu, 10 Sep 2020 06:33:01 +0000 (08:33 +0200)] 
BUILD: compiler: reserve the gcc version checks to the gcc compiler

Some checks on __GNUC__ imply that if it's undefined it will match a
low value but that's not always what we want, like for example in the
VAR_ARRAY definition which is not needed on tcc. Let's always be explicit
on these tests.

4 years agoBUILD: threads: better workaround for late loading of libgcc_s
Willy Tarreau [Wed, 9 Sep 2020 15:07:54 +0000 (17:07 +0200)] 
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).

4 years agoBUG/MEDIUM: mux-h1: always apply the timeout on half-closed connections
Willy Tarreau [Tue, 8 Sep 2020 13:40:57 +0000 (15:40 +0200)] 
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.

4 years agoBUG/MINOR: auth: report valid crypto(3) support depending on build options
Victor Kislov [Thu, 6 Aug 2020 16:21:39 +0000 (19:21 +0300)] 
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.

4 years agoDOC: ssl-load-extra-files only applies to certificates on bind lines
Jerome Magnin [Mon, 7 Sep 2020 09:55:57 +0000 (11:55 +0200)] 
DOC: ssl-load-extra-files only applies to certificates on bind lines

Be explicit about ssl-load-extra-files not applying to certificates
referenced with the crt keyword on server lines.

It must be backported in 2.2.