Commit Graph

143 Commits

Author SHA1 Message Date
Christopher Faulet
93a518f02a MINOR: standard: Add memvprintf function
Now memprintf relies on memvprintf. This new function does exactly what
memprintf did before, but it must be called with a va_list instead of a variable
number of arguments. So there is no change for every functions using
memprintf. But it is now also possible to have same functionnality from any
function with variadic arguments.
2017-10-31 11:36:12 +01:00
Willy Tarreau
1296382d0b CONTRIB: trace: add the possibility to place trace calls in the code
Now any call to trace() in the code will automatically appear interleaved
with the call sequence and timestamped in the trace file. They appear with
a '#' on the 3rd argument (caller's pointer) in order to make them easy to
spot. If the trace functionality is not used, a dmumy weak function is used
instead so that it doesn't require to recompile every time traces are
enabled/disabled.

The trace decoder knows how to deal with these messages, detects them and
indents them similarly to the currently traced function. This can be used
to print function arguments for example.

Note that we systematically flush the log when calling trace() to ensure we
never miss important events, so this may impact performance.

The trace() function uses the same format as printf() so it should be easy
to setup during debugging sessions.
2017-10-24 19:54:25 +02:00
Willy Tarreau
cb1949b8b3 MINOR: tools: add a portable timegm() alternative
timegm() is not provided everywhere and the documentation on how to
replace it is bogus as it proposes an inefficient and non-thread safe
alternative.

Here we reimplement everything needed to compute the number of seconds
since Epoch based on the broken down fields in struct tm. It is only
guaranteed to return correct values for correct inputs. It was successfully
tested with all possible 32-bit values of time_t converted to struct tm
using gmtime() and back to time_t using the legacy timegm() and this
function, and both functions always produced the same result.

Thanks to Benoît Garnier for an instructive discussion and detailed
explanations of the various time functions, leading to this solution.
2017-07-19 19:15:06 +02:00
Willy Tarreau
ed936c5d37 MINOR: tools: make debug_hexdump() take a string prefix
When dumping data at various places in the code, it's hard to figure
what is present where. To make this easier, this patch slightly modifies
debug_hexdump() to take a prefix string which is prepended in front of
each output line.
2017-06-02 15:49:31 +02:00
Willy Tarreau
9faef1e391 MINOR: tools: make debug_hexdump() use a const char for the string
There's no reason the string to be dumped should be a char *, it's
a const.
2017-06-02 15:49:31 +02:00
Jarno Huuskonen
577d5ac8ae CLEANUP: str2mask return code comment: non-zero -> zero. 2017-06-02 15:43:46 +02:00
Frédéric Lécaille
b82f742b78 MINOR: server: Add 'server-template' new keyword supported in backend sections.
This patch makes backend sections support 'server-template' new keyword.
Such 'server-template' objects are parsed similarly to a 'server' object
by parse_server() function, but its first arguments are as follows:
    server-template <ID prefix> <nb | range> <ip | fqdn>:<port> ...

The remaining arguments are the same as for 'server' lines.

With such server template declarations, servers may be allocated with IDs
built from <ID prefix> and <nb | range> arguments.

For instance declaring:
    server-template foo 1-5 google.com:80 ...
or
    server-template foo 5 google.com:80 ...

would be equivalent to declare:
    server foo1 google.com:80 ...
    server foo2 google.com:80 ...
    server foo3 google.com:80 ...
    server foo4 google.com:80 ...
    server foo5 google.com:80 ...
2017-04-21 15:42:10 +02:00
Willy Tarreau
73459797fd BUILD/MINOR: tools: fix build warning in debug_hexdump()
Commit 0ebb511 ("MINOR: tools: add a generic hexdump function for debugging")
introduced debug_hexdump() which is used to dump a memory area during
debugging sessions. This function can start at an unaligned offset and
uses a signed comparison to know where to start dumping from. But the
operation mixes signed and unsigned, making the test incorrect and causing
the following warnings to be emitted under Clang :

  src/standard.c:3775:14: warning: comparison of unsigned expression >= 0 is
        always true [-Wtautological-compare]
                          if (b + j >= 0 && b + j < len)
                              ~~~~~ ^  ~

Make "j" signed instead. At the moment this function is not used at all
so there's no impact. Thanks to Dmitry Sivachenko for reporting it. No
backport is needed.
2017-04-11 08:01:17 +02:00
Willy Tarreau
7b760c9c80 BUG/MEDIUM: tools: do not force an unresolved address to AF_INET:0.0.0.0
This prevents DNS from resolving IPv6-only servers in 1.7. Note, this
patch depends on the previous series :

  1. BUG/MINOR: tools: fix off-by-one in port size check
  2. BUG/MEDIUM: server: consider AF_UNSPEC as a valid address family
  3. MEDIUM: server: split the address and the port into two different fields
  4. MINOR: tools: make str2sa_range() return the port in a separate argument
  5. MINOR: server: take the destination port from the port field, not the addr
  6. MEDIUM: server: disable protocol validations when the server doesn't resolve

This fix (hence the whole series) must be backported to 1.7.
2017-01-11 12:44:33 +01:00
Willy Tarreau
48ef4c95b6 MINOR: tools: make str2sa_range() return the port in a separate argument
This will be needed so that we're don't have to extract it from the
returned address where it will not always be anymore (eg: for unresolved
servers).
2017-01-06 19:29:34 +01:00
Willy Tarreau
d7dad1bc49 BUG/MINOR: tools: fix off-by-one in port size check
port_to_str() checks that the port size is at least 5 characters instead
of at least 6. While in theory it could permit a buffer overflow, it's
harmless because all callers have at least 6 characters here.

This fix needs to be backported to 1.7, 1.6 and 1.5.
2017-01-06 16:46:22 +01:00
Willy Tarreau
0ebb511b3e MINOR: tools: add a generic hexdump function for debugging
debug_hexdump() prints to the requested output stream (typically stdout
or stderr) an hex dump of the blob passed in argument. This is useful
to help debug binary protocols.
2017-01-05 20:12:20 +01:00
Willy Tarreau
97c2ae13bc REORG: cli: move dump_text(), dump_text_line(), and dump_binary() to standard.c
These are general purpose functions, move them away.
2016-11-24 16:59:27 +01:00
David Carlier
327298c215 BUILD: fix build on Solaris 10/11
uint16_t instead of u_int16_t
None ISO fields of struct tm are not present, but
by zeroyfing it, on GNU and BSD systems tm_gmtoff
field will be set.

[wt: moved the memset into each of the date functions]
2016-11-22 12:04:19 +01:00
Willy Tarreau
ceccdd78a7 MEDIUM: tools: make str2sa_range() return the FQDN even when not resolving
This will be needed to later postpone server address resolution. We need the
FQDN even when it doesn't resolve. The caller then needs to check if fqdn was
set when resolve is null to detect that the address couldn't be parsed and
needs later resolution.
2016-11-09 14:24:20 +01:00
Willy Tarreau
dc3a9e830c CLEANUP: tools: make ipcpy() preserve the original port
ipcpy() is used to replace an IP address with another one, but it
doesn't preserve the original port so all callers have to do it
manually while it's trivial to do there. Better do it inside the
function.
2016-11-05 13:56:04 +01:00
Willy Tarreau
ecde7df11b MEDIUM: tools: make str2ip2() preserve existing ports
Often we need to call str2ip2() on an address which already contains a
port without replacing it, so let's ensure we preserve it even if the
family changes.
2016-11-05 13:56:04 +01:00
Baptiste Assmann
08396c87d0 MINOR: standard.c: ipcpy() function to copy an IP address from a struct sockaddr_storage into an other one
The function ipcpy() simply duplicates the IP address found in one
struct sockaddr_storage into an other struct sockaddr_storage.
It also update the family on the destination structure.

Memory of destination structure must be allocated and cleared by the
caller.
2016-08-14 12:16:43 +02:00
Baptiste Assmann
08b24cfdb2 MINOR: standard.c: ipcmp() function to compare 2 IP addresses stored in 2 struct sockaddr_storage
new ipcmp() function to compare 2 IP addresses stored in struct
sockaddr_storage.
Returns 0 if both addresses doesn't match and 1 if they do.
2016-08-14 12:16:27 +02:00
Willy Tarreau
16e015635c MINOR: tcp: add dst_is_local and src_is_local
It is sometimes needed in application server environments to easily tell
if a source is local to the machine or a remote one, without necessarily
knowing all the local addresses (dhcp, vrrp, etc). Similarly in transparent
proxy configurations it is sometimes desired to tell the difference between
local and remote destination addresses.

This patch adds two new sample fetch functions for this :

dst_is_local : boolean
  Returns true if the destination address of the incoming connection is local
  to the system, or false if the address doesn't exist on the system, meaning
  that it was intercepted in transparent mode. It can be useful to apply
  certain rules by default to forwarded traffic and other rules to the traffic
  targetting the real address of the machine. For example the stats page could
  be delivered only on this address, or SSH access could be locally redirected.
  Please note that the check involves a few system calls, so it's better to do
  it only once per connection.

src_is_local : boolean
  Returns true if the source address of the incoming connection is local to the
  system, or false if the address doesn't exist on the system, meaning that it
  comes from a remote machine. Note that UNIX addresses are considered local.
  It can be useful to apply certain access restrictions based on where the
  client comes from (eg: require auth or https for remote machines). Please
  note that the check involves a few system calls, so it's better to do it only
  once per connection.
2016-08-09 16:50:08 +02:00
Dragan Dosen
1a5d06032b MINOR: standard: add function "escape_string"
Similar to "escape_chunk", this function tries to prefix all characters
tagged in the <map> with the <escape> character. The specified <string>
contains the input to be escaped.
2016-07-26 15:25:32 +02:00
Willy Tarreau
eec1d3869d BUG/MEDIUM: dns: fix alignment issues in the DNS response parser
Alexander Lebedev reported that the DNS parser crashes in 1.6 with a bus
error on Sparc when it receives a response. This is obviously caused by
some alignment issues. The issue can also be reproduced on ARMv5 when
setting /proc/cpu/alignment to 4 (which helps debugging).

Two places cause this crash in turn, the first one is when the IP address
from the packet is compared to the current one, and the second place is
when the address is assigned because an unaligned address is passed to
update_server_addr().

This patch modifies these places to properly use memcpy() and memcmp()
to manipulate the unaligned data.

Nenad Merdanovic found another set of places specific to 1.7 in functions
in_net_ipv4() and in_net_ipv6(), which are used to compare networks. 1.6
has the functions but does not use them. There we perform a temporary copy
to a local variable to fix the problem. The type of the function's argument
is wrong since it's not necessarily aligned, so we change it for a const
void * instead.

This fix must be backported to 1.6. Note that in 1.6 the code is slightly
different, there's no rec[] array, the pointer is used directly from the
buffer.
2016-07-13 12:13:24 +02:00
Hubert Verstraete
831962e3b3 CLEANUP: fixed some usages of realloc leading to memory leak
Changed all the cases where the pointer passed to realloc is overwritten
by the pointer returned by realloc. The new function my_realloc2 has
been used except in function register_name. If register_name fails to
add a new variable because of an "out of memory" error, all the existing
variables remain valid. If we had used my_realloc2, the array of variables
would have been freed.
2016-06-29 10:45:18 +02:00
Maxime de Roucy
dc88785f9c MINOR: add list_append_word function
int list_append_word(struct list *li, const char *str, char **err)

Append a copy of string <str> (inside a wordlist) at the end of
the list <li>.
The caller is responsible for freeing the <err> and <str> copy memory
area using free().

On failure : return 0 and <err> filled with an error message.
2016-05-14 00:00:54 +02:00
Vincent Bernat
3c2f2f207f CLEANUP: remove unneeded casts
In C89, "void *" is automatically promoted to any pointer type. Casting
the result of malloc/calloc to the type of the LHS variable is therefore
unneeded.

Most of this patch was built using this Coccinelle patch:

@@
type T;
@@

- (T *)
  (\(lua_touserdata\|malloc\|calloc\|SSL_get_app_data\|hlua_checkudata\|lua_newuserdata\)(...))

@@
type T;
T *x;
void *data;
@@

  x =
- (T *)
  data

@@
type T;
T *x;
T *data;
@@

  x =
- (T *)
  data

Unfortunately, either Coccinelle or I is too limited to detect situation
where a complex RHS expression is of type "void *" and therefore casting
is not needed. Those cases were manually examined and corrected.
2016-04-03 14:17:42 +02:00
Benoit GARNIER
e2e5bde3f2 BUG/MINOR: log: Don't use strftime() which can clobber timezone if chrooted
The strftime() function can call tzset() internally on some platforms.
When haproxy is chrooted, the /etc/localtime file is not found, and some
implementations will clobber the content of the current timezone.

The GMT offset is computed by diffing the times returned by gmtime_r() and
localtime_r(). These variants are guaranteed to not call tzset() and were
already used in haproxy while chrooted, so they should be safe.

This patch must be backported to 1.6 and 1.5.
2016-03-17 05:30:03 +01:00
Benoit GARNIER
b413c2a759 BUG/MINOR: log: GMT offset not updated when entering/leaving DST
GMT offset used in local time formats was computed at startup, but was not updated when DST status changed while running.

For example these two RFC5424 syslog traces where emitted 5 seconds apart, just before and after DST changed:
  <14>1 2016-03-27T01:59:58+01:00 bunch-VirtualBox haproxy 2098 - - Connect ...
  <14>1 2016-03-27T03:00:03+01:00 bunch-VirtualBox haproxy 2098 - - Connect ...

It looked like they were emitted more than 1 hour apart, unlike with the fix:
  <14>1 2016-03-27T01:59:58+01:00 bunch-VirtualBox haproxy 3381 - - Connect ...
  <14>1 2016-03-27T03:00:03+02:00 bunch-VirtualBox haproxy 3381 - - Connect ...

This patch should be backported to 1.6 and partially to 1.5 (no fix needed in log.c).
2016-03-13 23:48:05 +01:00
Andreas Seltenreich
93f91c3082 BUG/MINOR: standard: Avoid free of non-allocated pointer
The original author forgot to dereference the argument to free in
parse_binary.  This may result in a crash on reading bad input from
the configuration file instead of a proper error message.

Found in HAProxy 1.5.14.
2016-03-13 07:46:54 +01:00
Thierry Fournier
70473a5f8c MINOR: common: mask conversion
Add function which converts network mask from bit length form
to struct in*_addr form.
2016-02-19 14:37:41 +01:00
Dragan Dosen
0edd10925d MINOR: standard: add function "escape_chunk"
This function tries to prefix all characters tagged in the <map> with the
<escape> character. The specified <chunk> contains the input to be
escaped.
2016-02-12 13:36:47 +01:00
Thierry Fournier
9312794ed7 MINOR: standard: add RFC HTTP date parser
This parser takes a string containing an HTTP date. It returns
a broken-down time struct. We must considers considers this
time as GMT. Maybe later the timezone will be taken in account.
2016-02-12 11:08:53 +01:00
Willy Tarreau
b631c291c9 MINOR: tools: make csv_enc_append() always start at the first byte of the chunk
csv_enc_append() returns a pointer to the beginning of the encoded
string, which makes it convenient to use in printf(). However it's not
convenient for use in chunks as it may leave an unused byte at the
beginning depending on the automatic quoting. Let's modify it to work
in two passes. First it looks for a character that requires escaping
using strpbrk(), and second it encodes the string. This way it
guarantees to always start at the first available byte of the chunk.
Additionally it made the code quite simpler.
2016-01-08 10:08:15 +01:00
Willy Tarreau
898529b4a8 MEDIUM: tools: add csv_enc_append() to preserve the original chunk
We have csv_enc() but there's no way to append some CSV-encoded data
to an existing chunk, so here we modify the existing function for this
and create an inlined version of csv_enc() which first resets the output
chunk. It will be handy to append data to an existing chunk without
having to use an extra temporary chunk, or to encode multiple strings
into a single chunk with chunk_newstr().

The patch is quite small, in fact most changes are typo fixes in the
comments.
2016-01-06 20:58:55 +01:00
mildis
ff5d510294 MINOR: config: allow IPv6 bracketed literals 2015-11-01 21:30:41 +01:00
Dmitry Sivachenko
eab7f3996f BUG/MEDIUM: str2ip: make getaddrinfo() consider local address selection policy
When first parameter to getaddrinfo() is not NULL (it is always not NULL
in str2ip()), on Linux AI_PASSIVE value for ai_flags is ignored. On
FreeBSD, when AI_PASSIVE is specified and hostname parameter is not NULL,
getaddrinfo() ignores local address selection policy, always returning
AAAA record. Pass zero ai_flags to behave correctly on FreeBSD, this
change should be no-op for Linux.

This fix should be backported to 1.5 as well, after some observation
period.
2015-10-02 01:01:58 +02:00
Thierry FOURNIER
7fe3be7281 MINOR: standard: avoid DNS resolution from the function str2sa_range()
This patch blocks the DNS resolution in the function str2sa_range(),
this is useful if the function is used during the HAProxy runtime.
2015-09-27 15:04:32 +02:00
Willy Tarreau
9f69f46d1f BUG/MINOR: tools: make str2sa_range() report unresolvable addresses
If an environment variable is used in an address, and is not set, it's
silently considered as ":" or "0.0.0.0:0" which is not correct as it
can hide environment issues and lead to unexpected behaviours. Let's
report this case when it happens.

This fix should be backported to 1.5.
2015-09-08 16:01:25 +02:00
Willy Tarreau
72b8c1f0aa MEDIUM: tools: make str2sa_range() optionally return the FQDN
The function does a bunch of things among which resolving environment
variables, skipping address family specifiers and trimming port ranges.
It is the only one which sees the complete host name before trying to
resolve it. The DNS resolving code needs to know the original hostname,
so we modify this function to optionally provide it to the caller.

Note that the function itself doesn't know if the host part was a host
or an address, but str2ip() knows that and can be asked not to try to
resolve. So we first try to parse the address without resolving and
try again with resolving enabled. This way we know if the address is
explicit or needs some kind of resolution.
2015-09-08 15:50:19 +02:00
Thierry FOURNIER
763a5d85f7 MINOR: standard: add 64 bits conversion functions
This patch adds 3 functions for 64 bit integer conversion.

 * lltoa_r : converts signed 64 bit integer to string
 * read_uint64 : converts from string to signed 64 bits integer with capping
 * read_int64 : converts from string to unsigned 64 bits integer with capping
2015-07-21 23:27:10 +02:00
Thierry FOURNIER
1480bd8dd2 MINOR: standard: add function that converts signed int to a string
This function is the same as "ultoa_r", but it takes a signed value
as input.
2015-06-13 22:59:14 +02:00
Baptiste Assmann
a68ca96375 MAJOR: server: add DNS-based server name resolution
Relies on the DNS protocol freshly implemented in HAProxy.
It performs a server IP addr resolution based on a server hostname.
2015-06-13 22:07:35 +02:00
Thierry FOURNIER
ddea626de4 MINOR: common: escape CSV strings
This function checks a string for using it in a CSV output format. If
the string contains one of the following four char <">, <,>, CR or LF,
the string is encapsulated between <"> and the <"> are escaped by a <"">
sequence.

The rounding by <"> is optionnal. It can be canceled, forced or the
function choose automatically the right way.
2015-05-28 17:47:19 +02:00
Thierry FOURNIER
9e7ec08976 BUG/MINOR: utf8: remove compilator warning
'c' is an unsigned int, obviously it is '>= 0'.
This patch remove the '>= 0' test.

this bug is repported by Dmitry Sivachenko
2015-03-13 14:10:28 +01:00
Thierry FOURNIER
58639a0ef3 MINOR: global: export function and permits to not resolve DNS names
exports the commonly used function str2ip. The function str2ip2 is
created and permits to not resolve DNS names.
2015-02-28 23:12:32 +01:00
Godbach
58048a2dc9 BUG/MINOR: parse: check the validity of size string in a more strict way
If a stick table is defined as below:
	stick-table type ip size 50ka expire 300s

HAProxy will stop parsing size after passing through "50k" and return the value
directly. But such format string of size should not be valid. The patch checks
the next character to report error if any.

Signed-off-by: Godbach <nylzhaowei@gmail.com>
2015-01-28 11:23:11 +01:00
Willy Tarreau
3ca1a883f9 MINOR: tools: add new round_2dig() function to round integers
This function rounds down an integer to the closest value having only
2 significant digits.
2015-01-15 19:02:27 +01:00
Thierry FOURNIER
317e1c4f1e MINOR: sample: add "json" converter
This converter escapes string to use it as json/ascii escaped string.
It can read UTF-8 with differents behavior on errors and encode it in
json/ascii.

json([<input-code>])
  Escapes the input string and produces an ASCII ouput string ready to use as a
  JSON string. The converter tries to decode the input string according to the
  <input-code> parameter. It can be "ascii", "utf8", "utf8s", "utf8"" or
  "utf8ps". The "ascii" decoder never fails. The "utf8" decoder detects 3 types
  of errors:
   - bad UTF-8 sequence (lone continuation byte, bad number of continuation
     bytes, ...)
   - invalid range (the decoded value is within a UTF-8 prohibited range),
   - code overlong (the value is encoded with more bytes than necessary).

  The UTF-8 JSON encoding can produce a "too long value" error when the UTF-8
  character is greater than 0xffff because the JSON string escape specification
  only authorizes 4 hex digits for the value encoding. The UTF-8 decoder exists
  in 4 variants designated by a combination of two suffix letters : "p" for
  "permissive" and "s" for "silently ignore". The behaviors of the decoders
  are :
   - "ascii"  : never fails ;
   - "utf8"   : fails on any detected errors ;
   - "utf8s"  : never fails, but removes characters corresponding to errors ;
   - "utf8p"  : accepts and fixes the overlong errors, but fails on any other
                error ;
   - "utf8ps" : never fails, accepts and fixes the overlong errors, but removes
                characters corresponding to the other errors.

  This converter is particularly useful for building properly escaped JSON for
  logging to servers which consume JSON-formated traffic logs.

  Example:
     capture request header user-agent len 150
     capture request header Host len 15
     log-format {"ip":"%[src]","user-agent":"%[capture.req.hdr(1),json]"}

  Input request from client 127.0.0.1:
     GET / HTTP/1.0
     User-Agent: Very "Ugly" UA 1/2

  Output log:
     {"ip":"127.0.0.1","user-agent":"Very \"Ugly\" UA 1\/2"}
2014-10-26 06:41:12 +01:00
Willy Tarreau
588297f2f9 MINOR: tools: add new functions to quote-encode strings
qstr() and cstr() will be used to quote-encode strings. The first one
does it unconditionally. The second one is aimed at CSV files where the
quote-encoding is only needed when the field contains a quote or a comma.
2014-06-16 18:20:14 +02:00
Simon Horman
75ab8bdb83 MEDIUM: Add port_to_str helper
This helper is similar to addr_to_str but
tries to convert the port rather than the address
of a struct sockaddr_storage.

This is in preparation for supporting
an external agent check.

Signed-off-by: Simon Horman <horms@verge.net.au>
2014-06-16 10:10:33 +02:00
Willy Tarreau
c874653bb4 BUILD: don't use type "uint" which is not portable
Dmitry Sivachenko reported that "uint" doesn't build on FreeBSD 10.
On Linux it's defined in sys/types.h and indicated as "old". Just
get rid of the very few occurrences.
2014-05-28 23:05:07 +02:00