2006-06-25 20:48:02 -04:00
|
|
|
/*
|
2020-06-03 12:09:46 -04:00
|
|
|
* include/haproxy/tools.h
|
2009-10-27 16:40:18 -04:00
|
|
|
* This files contains some general purpose functions and macros.
|
|
|
|
|
*
|
2020-06-03 12:09:46 -04:00
|
|
|
* Copyright (C) 2000-2020 Willy Tarreau - w@1wt.eu
|
2009-10-27 16:40:18 -04:00
|
|
|
*
|
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
|
* License as published by the Free Software Foundation, version 2.1
|
|
|
|
|
* exclusively.
|
|
|
|
|
*
|
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
|
*/
|
2006-06-25 20:48:02 -04:00
|
|
|
|
2020-06-03 12:09:46 -04:00
|
|
|
#ifndef _HAPROXY_TOOLS_H
|
|
|
|
|
#define _HAPROXY_TOOLS_H
|
2006-06-25 20:48:02 -04:00
|
|
|
|
2020-03-04 01:44:06 -05:00
|
|
|
#ifdef USE_BACKTRACE
|
2024-09-29 03:37:16 -04:00
|
|
|
// for backtrace() on Linux
|
2020-03-04 01:44:06 -05:00
|
|
|
#define _GNU_SOURCE
|
|
|
|
|
#endif
|
|
|
|
|
|
2024-09-20 17:14:41 -04:00
|
|
|
#include <errno.h>
|
2010-01-14 05:40:12 -05:00
|
|
|
#include <string.h>
|
2016-12-04 18:10:57 -05:00
|
|
|
#include <stdio.h>
|
2007-10-25 04:34:16 -04:00
|
|
|
#include <time.h>
|
2017-11-03 08:00:26 -04:00
|
|
|
#include <stdarg.h>
|
2015-04-29 11:13:35 -04:00
|
|
|
#include <sys/time.h>
|
2007-05-10 00:39:03 -04:00
|
|
|
#include <sys/types.h>
|
2012-09-04 08:18:33 -04:00
|
|
|
#include <sys/socket.h>
|
2012-09-02 16:34:23 -04:00
|
|
|
#include <sys/un.h>
|
2006-06-25 20:48:02 -04:00
|
|
|
#include <netinet/in.h>
|
2015-07-21 17:47:18 -04:00
|
|
|
#include <arpa/inet.h>
|
2020-06-03 12:09:46 -04:00
|
|
|
#include <import/eb32sctree.h>
|
2020-06-09 03:07:15 -04:00
|
|
|
#include <import/eb32tree.h>
|
2020-05-27 06:58:42 -04:00
|
|
|
#include <haproxy/api.h>
|
2020-06-02 04:22:45 -04:00
|
|
|
#include <haproxy/chunk.h>
|
2020-06-09 03:07:15 -04:00
|
|
|
#include <haproxy/intops.h>
|
2024-05-22 08:21:16 -04:00
|
|
|
#include <haproxy/global.h>
|
2020-06-02 11:02:59 -04:00
|
|
|
#include <haproxy/namespace-t.h>
|
2020-06-03 09:26:55 -04:00
|
|
|
#include <haproxy/protocol-t.h>
|
2020-06-03 12:09:46 -04:00
|
|
|
#include <haproxy/tools-t.h>
|
2014-06-16 09:16:40 -04:00
|
|
|
|
2024-09-29 03:37:16 -04:00
|
|
|
#if defined(USE_BACKTRACE) && defined(HA_HAVE_WORKING_BACKTRACE)
|
|
|
|
|
#include <execinfo.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
2006-06-25 20:48:02 -04:00
|
|
|
/****** string-specific macros and functions ******/
|
|
|
|
|
/* if a > max, then bound <a> to <max>. The macro returns the new <a> */
|
|
|
|
|
#define UBOUND(a, max) ({ typeof(a) b = (max); if ((a) > b) (a) = b; (a); })
|
|
|
|
|
|
|
|
|
|
/* if a < min, then bound <a> to <min>. The macro returns the new <a> */
|
|
|
|
|
#define LBOUND(a, min) ({ typeof(a) b = (min); if ((a) < b) (a) = b; (a); })
|
|
|
|
|
|
2020-06-03 11:49:00 -04:00
|
|
|
#define SWAP(a, b) do { typeof(a) t; t = a; a = b; b = t; } while(0)
|
|
|
|
|
|
2022-09-14 11:40:24 -04:00
|
|
|
/* use if you want to return a simple hash. Key 0 doesn't hash. */
|
|
|
|
|
#define HA_ANON_STR(key, str) hash_anon(key, str, "", "")
|
|
|
|
|
|
2022-09-29 04:36:11 -04:00
|
|
|
/* use if you want to return a hash like : ID('hash'). Key 0 doesn't hash. */
|
2022-09-14 11:40:24 -04:00
|
|
|
#define HA_ANON_ID(key, str) hash_anon(key, str, "ID(", ")")
|
|
|
|
|
|
|
|
|
|
/* use if you want to return a hash like : PATH('hash'). Key 0 doesn't hash. */
|
|
|
|
|
#define HA_ANON_PATH(key, str) hash_anon(key, str, "PATH(", ")")
|
|
|
|
|
|
2022-09-14 11:24:22 -04:00
|
|
|
/* use only in a function that contains an appctx (key comes from appctx). */
|
2025-04-24 05:17:07 -04:00
|
|
|
#define HA_ANON_CLI(str) hash_anon(appctx->cli_ctx.anon_key, str, "", "")
|
2022-09-14 11:24:22 -04:00
|
|
|
|
2022-09-14 11:40:24 -04:00
|
|
|
|
2006-06-25 20:48:02 -04:00
|
|
|
/*
|
|
|
|
|
* copies at most <size-1> chars from <src> to <dst>. Last char is always
|
|
|
|
|
* set to 0, unless <size> is 0. The number of chars copied is returned
|
|
|
|
|
* (excluding the terminating zero).
|
|
|
|
|
* This code has been optimized for size and speed : on x86, it's 45 bytes
|
|
|
|
|
* long, uses only registers, and consumes only 4 cycles per char.
|
|
|
|
|
*/
|
|
|
|
|
extern int strlcpy2(char *dst, const char *src, int size);
|
|
|
|
|
|
2024-10-25 11:04:37 -04:00
|
|
|
/*
|
|
|
|
|
* portable equivalent to POSIX strnlen():
|
|
|
|
|
* returns the number of bytes in the string pointed to by <s>, excluding
|
|
|
|
|
* the terminating null byte, but at most <maxlen>. The function does not
|
|
|
|
|
* look at characters passed <maxlen>.
|
|
|
|
|
*/
|
|
|
|
|
static inline size_t strnlen2(const char *s, size_t maxlen)
|
|
|
|
|
{
|
|
|
|
|
size_t len;
|
|
|
|
|
|
|
|
|
|
for (len = 0; len < maxlen && s[len]; len++)
|
|
|
|
|
;
|
|
|
|
|
return len;
|
|
|
|
|
}
|
|
|
|
|
|
2006-06-25 20:48:02 -04:00
|
|
|
/*
|
2007-10-25 06:14:10 -04:00
|
|
|
* This function simply returns a locally allocated string containing
|
2006-06-25 20:48:02 -04:00
|
|
|
* the ascii representation for number 'n' in decimal.
|
|
|
|
|
*/
|
2020-06-16 10:27:26 -04:00
|
|
|
extern THREAD_LOCAL int itoa_idx; /* index of next itoa_str to use */
|
2017-11-14 10:47:26 -05:00
|
|
|
extern THREAD_LOCAL char itoa_str[][171];
|
2022-07-18 07:58:17 -04:00
|
|
|
extern int build_is_static;
|
2010-01-04 08:54:38 -05:00
|
|
|
extern char *ultoa_r(unsigned long n, char *buffer, int size);
|
2015-07-06 17:09:52 -04:00
|
|
|
extern char *lltoa_r(long long int n, char *buffer, int size);
|
2015-06-06 13:14:59 -04:00
|
|
|
extern char *sltoa_r(long n, char *buffer, int size);
|
2009-03-29 07:41:58 -04:00
|
|
|
extern const char *ulltoh_r(unsigned long long n, char *buffer, int size);
|
MINOR: tools: implement trimming of floating point numbers
When using "%f" to print a float, it automatically gets 6 digits after
the decimal point and there's no way to automatically adjust to the
required ones by dropping trailing zeroes. This function does exactly
this and automatically drops the decimal point if all digits after it
were zeroes. This will make numbers more friendly in stats and makes
outputs shorter (e.g. JSON where everything is just a "number").
The function is designed to be easy to use with snprint() and chunks:
snprintf:
flt_trim(buf, 0, snprintf(buf, sizeof(buf), "%f", x));
chunk_printf:
out->data = flt_trim(out->area, 0, chunk_printf(out, "%f", x));
chunk_appendf:
size_t prev_data = out->data;
out->data = flt_trim(out->area, prev_data, chunk_appendf(out, "%f", x));
2021-05-08 04:28:53 -04:00
|
|
|
size_t flt_trim(char *buffer, size_t num_start, size_t len);
|
2021-05-08 01:35:00 -04:00
|
|
|
char *ftoa_r(double n, char *buffer, int size);
|
2007-10-25 06:14:10 -04:00
|
|
|
static inline const char *ultoa(unsigned long n)
|
|
|
|
|
{
|
|
|
|
|
return ultoa_r(n, itoa_str[0], sizeof(itoa_str[0]));
|
|
|
|
|
}
|
|
|
|
|
|
MINOR: tools: add minimal file name management
In proxies, stick-tables, servers, etc... at plenty of places we store
a file name and a line number. Some file names are the result of strdup()
(e.g. in proxies), others not (e.g. stick-tables) and leave dangling
pointers at the end of parsing. The risk of double-free is not null
either.
In order to stop this, let's first add a simple tool that allows to
register short strings inside a global list, these strings happening
to be server names. The strings are either duplicated and stored upon
failure to find them, or just added to this storage. Since file names
are not expected to disappear before the end of the process, for now
we don't even implement refcounting, and we free them all at the end.
There's already a drop_file_name() function to reset the pointer like
ha_free() used to do, and even if not strictly needed it's a good
habit to get used to doing it.
The strings are returned as const so that they're stored as-is in
structs, and that nasty free() calls are easily caught. The pointer
points to the char[] storage inside the node itself. This way later
if we want to implement refcounting, it will be trivial to just look
up a string and change its associated node's refcount. If needed,
comparisons can also be made on pointers.
For now they're not used yet and are released on deinit().
2024-09-19 08:56:01 -04:00
|
|
|
/* file names management */
|
|
|
|
|
const char *copy_file_name(const char *name);
|
|
|
|
|
void free_all_file_names();
|
|
|
|
|
|
|
|
|
|
/* This is only used as a marker for call places where a free() of a file name
|
|
|
|
|
* is expected to be performed, and to reset the pointer.
|
|
|
|
|
*/
|
|
|
|
|
static inline void drop_file_name(const char **name)
|
|
|
|
|
{
|
|
|
|
|
*name = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2012-01-24 05:15:39 -05:00
|
|
|
/*
|
|
|
|
|
* unsigned long long ASCII representation
|
|
|
|
|
*
|
|
|
|
|
* return the last char '\0' or NULL if no enough
|
|
|
|
|
* space in dst
|
|
|
|
|
*/
|
|
|
|
|
char *ulltoa(unsigned long long n, char *dst, size_t size);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* unsigned long ASCII representation
|
|
|
|
|
*
|
|
|
|
|
* return the last char '\0' or NULL if no enough
|
|
|
|
|
* space in dst
|
|
|
|
|
*/
|
|
|
|
|
char *ultoa_o(unsigned long n, char *dst, size_t size);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* signed long ASCII representation
|
|
|
|
|
*
|
|
|
|
|
* return the last char '\0' or NULL if no enough
|
|
|
|
|
* space in dst
|
|
|
|
|
*/
|
|
|
|
|
char *ltoa_o(long int n, char *dst, size_t size);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* signed long long ASCII representation
|
|
|
|
|
*
|
|
|
|
|
* return the last char '\0' or NULL if no enough
|
|
|
|
|
* space in dst
|
|
|
|
|
*/
|
|
|
|
|
char *lltoa(long long n, char *dst, size_t size);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* write a ascii representation of a unsigned into dst,
|
|
|
|
|
* return a pointer to the last character
|
|
|
|
|
* Pad the ascii representation with '0', using size.
|
|
|
|
|
*/
|
|
|
|
|
char *utoa_pad(unsigned int n, char *dst, size_t size);
|
|
|
|
|
|
2007-10-25 10:58:42 -04:00
|
|
|
/*
|
|
|
|
|
* This function simply returns a locally allocated string containing the ascii
|
|
|
|
|
* representation for number 'n' in decimal, unless n is 0 in which case it
|
|
|
|
|
* returns the alternate string (or an empty string if the alternate string is
|
|
|
|
|
* NULL). It use is intended for limits reported in reports, where it's
|
|
|
|
|
* desirable not to display anything if there is no limit. Warning! it shares
|
|
|
|
|
* the same vector as ultoa_r().
|
|
|
|
|
*/
|
|
|
|
|
extern const char *limit_r(unsigned long n, char *buffer, int size, const char *alt);
|
|
|
|
|
|
2012-12-23 12:00:29 -05:00
|
|
|
/* returns a locally allocated string containing the ASCII representation of
|
|
|
|
|
* the number 'n' in decimal. Up to NB_ITOA_STR calls may be used in the same
|
|
|
|
|
* function call (eg: printf), shared with the other similar functions making
|
|
|
|
|
* use of itoa_str[].
|
|
|
|
|
*/
|
|
|
|
|
static inline const char *U2A(unsigned long n)
|
|
|
|
|
{
|
|
|
|
|
const char *ret = ultoa_r(n, itoa_str[itoa_idx], sizeof(itoa_str[0]));
|
|
|
|
|
if (++itoa_idx >= NB_ITOA_STR)
|
|
|
|
|
itoa_idx = 0;
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* returns a locally allocated string containing the HTML representation of
|
|
|
|
|
* the number 'n' in decimal. Up to NB_ITOA_STR calls may be used in the same
|
|
|
|
|
* function call (eg: printf), shared with the other similar functions making
|
|
|
|
|
* use of itoa_str[].
|
|
|
|
|
*/
|
|
|
|
|
static inline const char *U2H(unsigned long long n)
|
|
|
|
|
{
|
|
|
|
|
const char *ret = ulltoh_r(n, itoa_str[itoa_idx], sizeof(itoa_str[0]));
|
|
|
|
|
if (++itoa_idx >= NB_ITOA_STR)
|
|
|
|
|
itoa_idx = 0;
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-08 01:35:00 -04:00
|
|
|
/* returns a locally allocated string containing the ASCII representation of
|
|
|
|
|
* the number 'n' in decimal. Up to NB_ITOA_STR calls may be used in the same
|
|
|
|
|
* function call (eg: printf), shared with the other similar functions making
|
|
|
|
|
* use of itoa_str[].
|
|
|
|
|
*/
|
|
|
|
|
static inline const char *F2A(double n)
|
|
|
|
|
{
|
|
|
|
|
const char *ret = ftoa_r(n, itoa_str[itoa_idx], sizeof(itoa_str[0]));
|
|
|
|
|
if (++itoa_idx >= NB_ITOA_STR)
|
|
|
|
|
itoa_idx = 0;
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* returns a locally allocated string containing the HTML representation of
|
|
|
|
|
* the number 'n' in decimal. Up to NB_ITOA_STR calls may be used in the same
|
|
|
|
|
* function call (eg: printf), shared with the other similar functions making
|
|
|
|
|
* use of itoa_str[].
|
|
|
|
|
*/
|
|
|
|
|
static inline const char *F2H(double n)
|
|
|
|
|
{
|
|
|
|
|
const char *ret = ftoa_r(n, itoa_str[itoa_idx], sizeof(itoa_str[0]));
|
|
|
|
|
if (++itoa_idx >= NB_ITOA_STR)
|
|
|
|
|
itoa_idx = 0;
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-24 03:05:19 -04:00
|
|
|
/* returns a locally allocated string containing the ASCII representation of
|
2012-12-23 12:00:29 -05:00
|
|
|
* the number 'n' in decimal. Up to NB_ITOA_STR calls may be used in the same
|
|
|
|
|
* function call (eg: printf), shared with the other similar functions making
|
|
|
|
|
* use of itoa_str[].
|
|
|
|
|
*/
|
|
|
|
|
static inline const char *LIM2A(unsigned long n, const char *alt)
|
|
|
|
|
{
|
|
|
|
|
const char *ret = limit_r(n, itoa_str[itoa_idx], sizeof(itoa_str[0]), alt);
|
|
|
|
|
if (++itoa_idx >= NB_ITOA_STR)
|
|
|
|
|
itoa_idx = 0;
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
2007-10-25 10:58:42 -04:00
|
|
|
|
2014-06-16 09:16:40 -04:00
|
|
|
/* returns a locally allocated string containing the quoted encoding of the
|
|
|
|
|
* input string. The output may be truncated to QSTR_SIZE chars, but it is
|
|
|
|
|
* guaranteed that the string will always be properly terminated. Quotes are
|
|
|
|
|
* encoded by doubling them as is commonly done in CSV files. QSTR_SIZE must
|
|
|
|
|
* always be at least 4 chars.
|
|
|
|
|
*/
|
|
|
|
|
const char *qstr(const char *str);
|
|
|
|
|
|
|
|
|
|
/* returns <str> or its quote-encoded equivalent if it contains at least one
|
|
|
|
|
* quote or a comma. This is aimed at build CSV-compatible strings.
|
|
|
|
|
*/
|
|
|
|
|
static inline const char *cstr(const char *str)
|
|
|
|
|
{
|
|
|
|
|
const char *p = str;
|
|
|
|
|
|
|
|
|
|
while (*p) {
|
|
|
|
|
if (*p == ',' || *p == '"')
|
|
|
|
|
return qstr(str);
|
|
|
|
|
p++;
|
|
|
|
|
}
|
|
|
|
|
return str;
|
|
|
|
|
}
|
|
|
|
|
|
2006-06-25 20:48:02 -04:00
|
|
|
/*
|
|
|
|
|
* Returns non-zero if character <s> is a hex digit (0-9, a-f, A-F), else zero.
|
|
|
|
|
*/
|
|
|
|
|
extern int ishex(char s);
|
|
|
|
|
|
2007-12-02 12:45:09 -05:00
|
|
|
/*
|
|
|
|
|
* Checks <name> for invalid characters. Valid chars are [A-Za-z0-9_:.-]. If an
|
|
|
|
|
* invalid character is found, a pointer to it is returned. If everything is
|
|
|
|
|
* fine, NULL is returned.
|
|
|
|
|
*/
|
|
|
|
|
extern const char *invalid_char(const char *name);
|
|
|
|
|
|
2008-05-23 17:49:32 -04:00
|
|
|
/*
|
2017-04-13 12:24:23 -04:00
|
|
|
* Checks <name> for invalid characters. Valid chars are [A-Za-z0-9_.-].
|
2008-05-23 17:49:32 -04:00
|
|
|
* If an invalid character is found, a pointer to it is returned.
|
|
|
|
|
* If everything is fine, NULL is returned.
|
|
|
|
|
*/
|
|
|
|
|
extern const char *invalid_domainchar(const char *name);
|
|
|
|
|
|
2017-04-13 12:24:23 -04:00
|
|
|
/*
|
|
|
|
|
* Checks <name> for invalid characters. Valid chars are [A-Za-z_.-].
|
|
|
|
|
* If an invalid character is found, a pointer to it is returned.
|
|
|
|
|
* If everything is fine, NULL is returned.
|
|
|
|
|
*/
|
|
|
|
|
extern const char *invalid_prefix_char(const char *name);
|
|
|
|
|
|
2020-02-14 12:25:17 -05:00
|
|
|
/* returns true if <c> is an identifier character, that is, a digit, a letter,
|
2020-02-17 00:34:11 -05:00
|
|
|
* or '-', '+', '_', ':' or '.'. This is usable for proxy names, server names,
|
|
|
|
|
* ACL names, sample fetch names, and converter names.
|
2020-02-14 12:25:17 -05:00
|
|
|
*/
|
|
|
|
|
static inline int is_idchar(char c)
|
|
|
|
|
{
|
2020-02-25 02:16:33 -05:00
|
|
|
return isalnum((unsigned char)c) ||
|
2020-02-17 00:34:11 -05:00
|
|
|
c == '.' || c == '_' || c == '-' || c == '+' || c == ':';
|
2020-02-14 12:25:17 -05:00
|
|
|
}
|
|
|
|
|
|
2011-03-04 09:31:53 -05:00
|
|
|
/*
|
|
|
|
|
* converts <str> to a locally allocated struct sockaddr_storage *, and a
|
2009-06-10 05:09:37 -04:00
|
|
|
* port range consisting in two integers. The low and high end are always set
|
|
|
|
|
* even if the port is unspecified, in which case (0,0) is returned. The low
|
2011-03-04 09:31:53 -05:00
|
|
|
* port is set in the sockaddr. Thus, it is enough to check the size of the
|
2009-06-10 05:09:37 -04:00
|
|
|
* returned range to know if an array must be allocated or not. The format is
|
2011-03-04 09:31:53 -05:00
|
|
|
* "addr[:[port[-port]]]", where "addr" can be a dotted IPv4 address, an IPv6
|
|
|
|
|
* address, a host name, or empty or "*" to indicate INADDR_ANY. If an IPv6
|
|
|
|
|
* address wants to ignore port, it must be terminated by a trailing colon (':').
|
|
|
|
|
* The IPv6 '::' address is IN6ADDR_ANY, so in order to bind to a given port on
|
|
|
|
|
* IPv6, use ":::port". NULL is returned if the host part cannot be resolved.
|
2013-03-04 12:22:00 -05:00
|
|
|
* If <pfx> is non-null, it is used as a string prefix before any path-based
|
2020-09-04 09:30:46 -04:00
|
|
|
* address (typically the path to a unix socket).
|
2009-06-10 05:09:37 -04:00
|
|
|
*/
|
2020-09-16 12:25:03 -04:00
|
|
|
struct sockaddr_storage *str2sa_range(const char *str, int *port, int *low, int *high, int *fd,
|
2023-11-09 05:19:24 -05:00
|
|
|
struct protocol **proto, struct net_addr_type *sa_type,
|
2024-08-26 05:50:24 -04:00
|
|
|
char **err, const char *pfx, char **fqdn, int *alt, unsigned int opts);
|
2009-06-10 05:09:37 -04:00
|
|
|
|
2020-11-20 03:28:26 -05:00
|
|
|
|
|
|
|
|
/* converts <addr> and <port> into a string representation of the address and port. This is sort
|
|
|
|
|
* of an inverse of str2sa_range, with some restrictions. The supported families are AF_INET,
|
|
|
|
|
* AF_INET6, AF_UNIX, and AF_CUST_SOCKPAIR. If the family is unsopported NULL is returned.
|
2025-03-10 17:25:09 -04:00
|
|
|
* If port is special value '-1', then only the address is represented and <map_ports> is ignored.
|
2020-11-20 03:28:26 -05:00
|
|
|
* If map_ports is true, then the sign of the port is included in the output, to indicate it is
|
|
|
|
|
* relative to the incoming port. AF_INET and AF_INET6 will be in the form "<addr>:<port>".
|
|
|
|
|
* AF_UNIX will either be just the path (if using a pathname) or "abns@<path>" if it is abstract.
|
|
|
|
|
* AF_CUST_SOCKPAIR will be of the form "sockpair@<fd>".
|
|
|
|
|
*
|
|
|
|
|
* The returned char* is allocated, and it is the responsibility of the caller to free it.
|
|
|
|
|
*/
|
|
|
|
|
char *sa2str(const struct sockaddr_storage *addr, int port, int map_ports);
|
|
|
|
|
|
2010-01-26 11:36:17 -05:00
|
|
|
/* converts <str> to a struct in_addr containing a network mask. It can be
|
|
|
|
|
* passed in dotted form (255.255.255.0) or in CIDR form (24). It returns 1
|
2017-05-21 10:32:21 -04:00
|
|
|
* if the conversion succeeds otherwise zero.
|
2010-01-26 11:36:17 -05:00
|
|
|
*/
|
|
|
|
|
int str2mask(const char *str, struct in_addr *mask);
|
|
|
|
|
|
2018-01-25 10:24:49 -05:00
|
|
|
/* converts <str> to a struct in6_addr containing a network mask. It can be
|
2018-02-20 11:02:18 -05:00
|
|
|
* passed in quadruplet form (ffff:ffff::) or in CIDR form (64). It returns 1
|
2018-01-25 10:24:49 -05:00
|
|
|
* if the conversion succeeds otherwise zero.
|
|
|
|
|
*/
|
|
|
|
|
int str2mask6(const char *str, struct in6_addr *mask);
|
|
|
|
|
|
2013-12-14 09:39:02 -05:00
|
|
|
/* convert <cidr> to struct in_addr <mask>. It returns 1 if the conversion
|
|
|
|
|
* succeeds otherwise non-zero.
|
|
|
|
|
*/
|
|
|
|
|
int cidr2dotted(int cidr, struct in_addr *mask);
|
|
|
|
|
|
2006-06-25 20:48:02 -04:00
|
|
|
/*
|
2007-05-08 12:28:09 -04:00
|
|
|
* converts <str> to two struct in_addr* which must be pre-allocated.
|
2006-06-25 20:48:02 -04:00
|
|
|
* The format is "addr[/mask]", where "addr" cannot be empty, and mask
|
2020-03-10 03:06:11 -04:00
|
|
|
* is optional and either in the dotted or CIDR notation.
|
2006-06-25 20:48:02 -04:00
|
|
|
* Note: "addr" can also be a hostname. Returns 1 if OK, 0 if error.
|
|
|
|
|
*/
|
2014-02-11 09:23:04 -05:00
|
|
|
int str2net(const char *str, int resolve, struct in_addr *addr, struct in_addr *mask);
|
2006-06-25 20:48:02 -04:00
|
|
|
|
2014-11-25 06:02:25 -05:00
|
|
|
/* str2ip and str2ip2:
|
|
|
|
|
*
|
|
|
|
|
* converts <str> to a struct sockaddr_storage* provided by the caller. The
|
|
|
|
|
* caller must have zeroed <sa> first, and may have set sa->ss_family to force
|
|
|
|
|
* parse a specific address format. If the ss_family is 0 or AF_UNSPEC, then
|
|
|
|
|
* the function tries to guess the address family from the syntax. If the
|
|
|
|
|
* family is forced and the format doesn't match, an error is returned. The
|
|
|
|
|
* string is assumed to contain only an address, no port. The address can be a
|
|
|
|
|
* dotted IPv4 address, an IPv6 address, a host name, or empty or "*" to
|
|
|
|
|
* indicate INADDR_ANY. NULL is returned if the host part cannot be resolved.
|
|
|
|
|
* The return address will only have the address family and the address set,
|
|
|
|
|
* all other fields remain zero. The string is not supposed to be modified.
|
|
|
|
|
* The IPv6 '::' address is IN6ADDR_ANY.
|
|
|
|
|
*
|
|
|
|
|
* str2ip2:
|
|
|
|
|
*
|
|
|
|
|
* If <resolve> is set, this function try to resolve DNS, otherwise, it returns
|
|
|
|
|
* NULL result.
|
|
|
|
|
*/
|
|
|
|
|
struct sockaddr_storage *str2ip2(const char *str, struct sockaddr_storage *sa, int resolve);
|
|
|
|
|
static inline struct sockaddr_storage *str2ip(const char *str, struct sockaddr_storage *sa)
|
|
|
|
|
{
|
|
|
|
|
return str2ip2(str, sa, 1);
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-27 16:49:47 -04:00
|
|
|
/*
|
|
|
|
|
* converts <str> to two struct in6_addr* which must be pre-allocated.
|
|
|
|
|
* The format is "addr[/mask]", where "addr" cannot be empty, and mask
|
2020-03-10 03:06:11 -04:00
|
|
|
* is an optional number of bits (128 being the default).
|
2012-04-27 16:49:47 -04:00
|
|
|
* Returns 1 if OK, 0 if error.
|
|
|
|
|
*/
|
|
|
|
|
int str62net(const char *str, struct in6_addr *addr, unsigned char *mask);
|
|
|
|
|
|
2009-09-19 01:54:16 -04:00
|
|
|
/*
|
|
|
|
|
* Parse IP address found in url.
|
|
|
|
|
*/
|
2011-03-10 16:26:24 -05:00
|
|
|
int url2ipv4(const char *addr, struct in_addr *dst);
|
2009-09-19 01:54:16 -04:00
|
|
|
|
2007-11-29 09:43:32 -05:00
|
|
|
/*
|
2011-03-10 16:26:24 -05:00
|
|
|
* Resolve destination server from URL. Convert <str> to a sockaddr_storage*.
|
2007-11-29 09:43:32 -05:00
|
|
|
*/
|
2014-03-21 09:51:46 -04:00
|
|
|
int url2sa(const char *url, int ulen, struct sockaddr_storage *addr, struct split_url *out);
|
2007-11-29 09:43:32 -05:00
|
|
|
|
2011-09-04 18:36:48 -04:00
|
|
|
/* Tries to convert a sockaddr_storage address to text form. Upon success, the
|
|
|
|
|
* address family is returned so that it's easy for the caller to adapt to the
|
|
|
|
|
* output format. Zero is returned if the address family is not supported. -1
|
|
|
|
|
* is returned upon error, with errno set. AF_INET, AF_INET6 and AF_UNIX are
|
|
|
|
|
* supported.
|
|
|
|
|
*/
|
2019-04-25 11:48:16 -04:00
|
|
|
int addr_to_str(const struct sockaddr_storage *addr, char *str, int size);
|
2011-09-04 18:36:48 -04:00
|
|
|
|
2014-06-15 20:39:41 -04:00
|
|
|
/* Tries to convert a sockaddr_storage port to text form. Upon success, the
|
|
|
|
|
* address family is returned so that it's easy for the caller to adapt to the
|
|
|
|
|
* output format. Zero is returned if the address family is not supported. -1
|
|
|
|
|
* is returned upon error, with errno set. AF_INET, AF_INET6 and AF_UNIX are
|
|
|
|
|
* supported.
|
|
|
|
|
*/
|
2019-04-25 11:48:16 -04:00
|
|
|
int port_to_str(const struct sockaddr_storage *addr, char *str, int size);
|
2014-06-15 20:39:41 -04:00
|
|
|
|
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 10:46:18 -04:00
|
|
|
/* check if the given address is local to the system or not. It will return
|
|
|
|
|
* -1 when it's not possible to know, 0 when the address is not local, 1 when
|
|
|
|
|
* it is. We don't want to iterate over all interfaces for this (and it is not
|
|
|
|
|
* portable). So instead we try to bind in UDP to this address on a free non
|
|
|
|
|
* privileged port and to connect to the same address, port 0 (connect doesn't
|
|
|
|
|
* care). If it succeeds, we own the address. Note that non-inet addresses are
|
|
|
|
|
* considered local since they're most likely AF_UNIX.
|
|
|
|
|
*/
|
|
|
|
|
int addr_is_local(const struct netns_entry *ns,
|
|
|
|
|
const struct sockaddr_storage *orig);
|
|
|
|
|
|
2006-06-25 20:48:02 -04:00
|
|
|
/* will try to encode the string <string> replacing all characters tagged in
|
|
|
|
|
* <map> with the hexadecimal representation of their ASCII-code (2 digits)
|
|
|
|
|
* prefixed by <escape>, and will store the result between <start> (included)
|
|
|
|
|
* and <stop> (excluded), and will always terminate the string with a '\0'
|
BUG/MINOR: tools/log: invalid encode_{chunk,string} usage
encode_{chunk,string}() is often found to be used this way:
ret = encode_{chunk,string}(start, stop...)
if (ret == NULL || *ret != '\0') {
//error
}
//success
Indeed, encode_{chunk,string} will always try to add terminating NULL byte
to the output string, unless no space is available for even 1 byte.
However, it means that for the caller to be able to spot an error, then it
must provide a buffer (here: start) which is already initialized.
But this is wrong: not only this is very tricky to use, but since those
functions don't return NULL on failure, then if the output buffer was not
properly initialized prior to calling the function, the caller will
perform invalid reads when checking for failure this way. Moreover, even
if the buffer is initialized, we cannot reliably tell if the function
actually failed this way because if the buffer was previously initialized
with NULL byte, then the caller might think that the call actually
succeeded (since the function didn't return NULL and didn't update the
buffer).
Also, sess_build_logline() relies lf_encode_{chunk,string}() functions
which are in fact wrappers for encode_{chunk,string}() functions and thus
exhibit the same error handling mechanism. It turns out that
sess_build_logline() makes unsafe use of those functions because it uses
the error-checking logic mentionned above while buffer (tmplog) is not
guaranteed to be initialized when entering the function. This may
ultimately cause malfunctions or invalid reads if the output buffer is
lacking space.
To fix the issue once and for all and prevent similar bugs from being
introduced, we make it so encode_{string, chunk} and escape_string()
(based on encode_string()) now explicitly return NULL on failure
(when the function failed to write at least the ending NULL byte)
lf_encode_{string,chunk}() helpers had to be patched as well due to code
duplication.
This should be backported to all stable versions.
[ada: for 2.4 and 2.6 the patch won't apply as-is, it might be helpful to
backport ae1e14d65 ("CLEANUP: tools: removing escape_chunk() function")
first, considering it's not very relevant to maintain a dead function]
2024-04-09 05:44:54 -04:00
|
|
|
* before <stop>. If bytes are missing between <start> and <stop>, then the
|
|
|
|
|
* conversion will be incomplete and truncated.
|
2006-06-25 20:48:02 -04:00
|
|
|
* The input string must also be zero-terminated.
|
BUG/MINOR: tools/log: invalid encode_{chunk,string} usage
encode_{chunk,string}() is often found to be used this way:
ret = encode_{chunk,string}(start, stop...)
if (ret == NULL || *ret != '\0') {
//error
}
//success
Indeed, encode_{chunk,string} will always try to add terminating NULL byte
to the output string, unless no space is available for even 1 byte.
However, it means that for the caller to be able to spot an error, then it
must provide a buffer (here: start) which is already initialized.
But this is wrong: not only this is very tricky to use, but since those
functions don't return NULL on failure, then if the output buffer was not
properly initialized prior to calling the function, the caller will
perform invalid reads when checking for failure this way. Moreover, even
if the buffer is initialized, we cannot reliably tell if the function
actually failed this way because if the buffer was previously initialized
with NULL byte, then the caller might think that the call actually
succeeded (since the function didn't return NULL and didn't update the
buffer).
Also, sess_build_logline() relies lf_encode_{chunk,string}() functions
which are in fact wrappers for encode_{chunk,string}() functions and thus
exhibit the same error handling mechanism. It turns out that
sess_build_logline() makes unsafe use of those functions because it uses
the error-checking logic mentionned above while buffer (tmplog) is not
guaranteed to be initialized when entering the function. This may
ultimately cause malfunctions or invalid reads if the output buffer is
lacking space.
To fix the issue once and for all and prevent similar bugs from being
introduced, we make it so encode_{string, chunk} and escape_string()
(based on encode_string()) now explicitly return NULL on failure
(when the function failed to write at least the ending NULL byte)
lf_encode_{string,chunk}() helpers had to be patched as well due to code
duplication.
This should be backported to all stable versions.
[ada: for 2.4 and 2.6 the patch won't apply as-is, it might be helpful to
backport ae1e14d65 ("CLEANUP: tools: removing escape_chunk() function")
first, considering it's not very relevant to maintain a dead function]
2024-04-09 05:44:54 -04:00
|
|
|
*
|
|
|
|
|
* Return the address of the \0 character, or NULL on error
|
2006-06-25 20:48:02 -04:00
|
|
|
*/
|
|
|
|
|
extern const char hextab[];
|
2022-12-20 05:11:05 -05:00
|
|
|
extern long query_encode_map[];
|
2006-06-25 20:48:02 -04:00
|
|
|
char *encode_string(char *start, char *stop,
|
2019-06-07 05:10:07 -04:00
|
|
|
const char escape, const long *map,
|
2006-06-25 20:48:02 -04:00
|
|
|
const char *string);
|
|
|
|
|
|
2014-03-17 07:01:13 -04:00
|
|
|
/*
|
|
|
|
|
* Same behavior, except that it encodes chunk <chunk> instead of a string.
|
|
|
|
|
*/
|
|
|
|
|
char *encode_chunk(char *start, char *stop,
|
2019-06-07 05:10:07 -04:00
|
|
|
const char escape, const long *map,
|
2018-07-13 05:56:34 -04:00
|
|
|
const struct buffer *chunk);
|
2014-03-17 07:01:13 -04:00
|
|
|
|
2016-07-22 10:00:31 -04:00
|
|
|
/*
|
|
|
|
|
* Tries to prefix characters tagged in the <map> with the <escape>
|
2022-09-20 08:33:18 -04:00
|
|
|
* character. The input <string> is processed until string_stop
|
|
|
|
|
* is reached or NULL-byte is encountered. The result will
|
2016-07-22 10:00:31 -04:00
|
|
|
* be stored between <start> (included) and <stop> (excluded). This
|
|
|
|
|
* function will always try to terminate the resulting string with a '\0'
|
BUG/MINOR: tools/log: invalid encode_{chunk,string} usage
encode_{chunk,string}() is often found to be used this way:
ret = encode_{chunk,string}(start, stop...)
if (ret == NULL || *ret != '\0') {
//error
}
//success
Indeed, encode_{chunk,string} will always try to add terminating NULL byte
to the output string, unless no space is available for even 1 byte.
However, it means that for the caller to be able to spot an error, then it
must provide a buffer (here: start) which is already initialized.
But this is wrong: not only this is very tricky to use, but since those
functions don't return NULL on failure, then if the output buffer was not
properly initialized prior to calling the function, the caller will
perform invalid reads when checking for failure this way. Moreover, even
if the buffer is initialized, we cannot reliably tell if the function
actually failed this way because if the buffer was previously initialized
with NULL byte, then the caller might think that the call actually
succeeded (since the function didn't return NULL and didn't update the
buffer).
Also, sess_build_logline() relies lf_encode_{chunk,string}() functions
which are in fact wrappers for encode_{chunk,string}() functions and thus
exhibit the same error handling mechanism. It turns out that
sess_build_logline() makes unsafe use of those functions because it uses
the error-checking logic mentionned above while buffer (tmplog) is not
guaranteed to be initialized when entering the function. This may
ultimately cause malfunctions or invalid reads if the output buffer is
lacking space.
To fix the issue once and for all and prevent similar bugs from being
introduced, we make it so encode_{string, chunk} and escape_string()
(based on encode_string()) now explicitly return NULL on failure
(when the function failed to write at least the ending NULL byte)
lf_encode_{string,chunk}() helpers had to be patched as well due to code
duplication.
This should be backported to all stable versions.
[ada: for 2.4 and 2.6 the patch won't apply as-is, it might be helpful to
backport ae1e14d65 ("CLEANUP: tools: removing escape_chunk() function")
first, considering it's not very relevant to maintain a dead function]
2024-04-09 05:44:54 -04:00
|
|
|
* before <stop>.
|
|
|
|
|
*
|
|
|
|
|
* Return the address of the \0 character, or NULL on error
|
2016-07-22 10:00:31 -04:00
|
|
|
*/
|
|
|
|
|
char *escape_string(char *start, char *stop,
|
2019-06-07 05:10:07 -04:00
|
|
|
const char escape, const long *map,
|
2022-09-20 08:33:18 -04:00
|
|
|
const char *string, const char *string_stop);
|
2016-07-22 10:00:31 -04:00
|
|
|
|
2024-04-22 11:38:44 -04:00
|
|
|
/* Below are RFC8949 compliant cbor encode helper functions, see source
|
|
|
|
|
* file for functions descriptions
|
|
|
|
|
*/
|
|
|
|
|
char *cbor_encode_uint64_prefix(struct cbor_encode_ctx *ctx,
|
|
|
|
|
char *start, char *stop,
|
|
|
|
|
uint64_t value, uint8_t prefix);
|
|
|
|
|
char *cbor_encode_int64(struct cbor_encode_ctx *ctx,
|
|
|
|
|
char *start, char *stop, int64_t value);
|
|
|
|
|
char *cbor_encode_bytes_prefix(struct cbor_encode_ctx *ctx,
|
|
|
|
|
char *start, char *stop,
|
|
|
|
|
const char *bytes, size_t len,
|
|
|
|
|
uint8_t prefix);
|
|
|
|
|
char *cbor_encode_bytes(struct cbor_encode_ctx *ctx,
|
|
|
|
|
char *start, char *stop,
|
|
|
|
|
const char *bytes, size_t len);
|
|
|
|
|
char *cbor_encode_text(struct cbor_encode_ctx *ctx,
|
|
|
|
|
char *start, char *stop,
|
|
|
|
|
const char *text, size_t len);
|
|
|
|
|
|
2015-05-28 10:00:28 -04:00
|
|
|
/* Check 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.
|
|
|
|
|
* <str> is the input string to be escaped. The function assumes that
|
|
|
|
|
* the input string is null-terminated.
|
|
|
|
|
*
|
|
|
|
|
* If <quote> is 0, the result is returned escaped but without double quote.
|
2016-01-06 12:07:04 -05:00
|
|
|
* It is useful if the escaped string is used between double quotes in the
|
2015-05-28 10:00:28 -04:00
|
|
|
* format.
|
|
|
|
|
*
|
2024-01-23 09:44:32 -05:00
|
|
|
* printf("..., \"%s\", ...\r\n", csv_enc(str, 0, 0, &trash));
|
2015-05-28 10:00:28 -04:00
|
|
|
*
|
2016-01-06 12:07:04 -05:00
|
|
|
* If <quote> is 1, the converter puts the quotes only if any character is
|
|
|
|
|
* escaped. If <quote> is 2, the converter always puts the quotes.
|
2015-05-28 10:00:28 -04:00
|
|
|
*
|
2024-01-23 09:44:32 -05:00
|
|
|
* If <oneline> is not 0, CRs are skipped and LFs are replaced by spaces.
|
|
|
|
|
* This re-format multi-lines strings to only one line. The purpose is to
|
|
|
|
|
* allow a line by line parsing but also to keep the output compliant with
|
|
|
|
|
* the CLI witch uses LF to defines the end of the response.
|
|
|
|
|
*
|
|
|
|
|
* If <oneline> is 2, In addition to previous action, the trailing spaces are
|
|
|
|
|
* removed.
|
|
|
|
|
*
|
2016-01-06 12:07:04 -05:00
|
|
|
* <output> is a struct chunk used for storing the output string.
|
2015-05-28 10:00:28 -04:00
|
|
|
*
|
2016-01-06 12:07:04 -05:00
|
|
|
* The function returns the converted string on its output. If an error
|
|
|
|
|
* occurs, the function returns an empty string. This type of output is useful
|
2015-05-28 10:00:28 -04:00
|
|
|
* for using the function directly as printf() argument.
|
|
|
|
|
*
|
2016-01-06 12:07:04 -05:00
|
|
|
* If the output buffer is too short to contain the input string, the result
|
2015-05-28 10:00:28 -04:00
|
|
|
* is truncated.
|
2016-01-06 12:07:04 -05:00
|
|
|
*
|
|
|
|
|
* This function appends the encoding to the existing output chunk. Please
|
|
|
|
|
* use csv_enc() instead if you want to replace the output chunk.
|
2015-05-28 10:00:28 -04:00
|
|
|
*/
|
2024-01-23 09:44:32 -05:00
|
|
|
const char *csv_enc_append(const char *str, int quote, int online,
|
|
|
|
|
struct buffer *output);
|
2016-01-06 12:07:04 -05:00
|
|
|
|
|
|
|
|
/* same as above but the output chunk is reset first */
|
2024-01-23 09:44:32 -05:00
|
|
|
static inline const char *csv_enc(const char *str, int quote, int oneline,
|
2018-07-13 05:56:34 -04:00
|
|
|
struct buffer *output)
|
2016-01-06 12:07:04 -05:00
|
|
|
{
|
|
|
|
|
chunk_reset(output);
|
2024-01-23 09:44:32 -05:00
|
|
|
return csv_enc_append(str, quote, oneline, output);
|
2016-01-06 12:07:04 -05:00
|
|
|
}
|
2015-05-28 10:00:28 -04:00
|
|
|
|
2011-05-31 12:06:18 -04:00
|
|
|
/* Decode an URL-encoded string in-place. The resulting string might
|
|
|
|
|
* be shorter. If some forbidden characters are found, the conversion is
|
|
|
|
|
* aborted, the string is truncated before the issue and non-zero is returned,
|
|
|
|
|
* otherwise the operation returns non-zero indicating success.
|
2020-04-23 11:54:47 -04:00
|
|
|
* If the 'in_form' argument is non-nul the string is assumed to be part of
|
|
|
|
|
* an "application/x-www-form-urlencoded" encoded string, and the '+' will be
|
|
|
|
|
* turned to a space. If it's zero, this will only be done after a question
|
|
|
|
|
* mark ('?').
|
2011-05-31 12:06:18 -04:00
|
|
|
*/
|
2020-04-23 11:54:47 -04:00
|
|
|
int url_decode(char *string, int in_form);
|
2011-05-31 12:06:18 -04:00
|
|
|
|
2009-09-07 05:00:31 -04:00
|
|
|
unsigned int inetaddr_host(const char *text);
|
|
|
|
|
unsigned int inetaddr_host_lim(const char *text, const char *stop);
|
2010-10-15 17:21:42 -04:00
|
|
|
unsigned int inetaddr_host_lim_ret(char *text, char *stop, char **ret);
|
2007-03-04 12:06:08 -05:00
|
|
|
|
2022-09-14 11:40:24 -04:00
|
|
|
/* Function that hashes or not a string according to the anonymizing key (scramble). */
|
|
|
|
|
const char *hash_anon(uint32_t scramble, const char *string2hash, const char *prefix, const char *suffix);
|
|
|
|
|
|
|
|
|
|
/* Function that hashes or not an ip according to the ipstring entered */
|
2022-09-29 04:25:31 -04:00
|
|
|
const char * hash_ipanon(uint32_t scramble, char *ipstring, int hasport);
|
2022-09-14 11:40:24 -04:00
|
|
|
|
2009-10-10 14:11:17 -04:00
|
|
|
static inline char *cut_crlf(char *s) {
|
|
|
|
|
|
2013-02-13 03:48:00 -05:00
|
|
|
while (*s != '\r' && *s != '\n') {
|
2009-10-10 14:11:17 -04:00
|
|
|
char *p = s++;
|
|
|
|
|
|
|
|
|
|
if (!*p)
|
|
|
|
|
return p;
|
|
|
|
|
}
|
|
|
|
|
|
2013-02-13 03:48:00 -05:00
|
|
|
*s++ = '\0';
|
2009-10-10 14:11:17 -04:00
|
|
|
|
|
|
|
|
return s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline char *ltrim(char *s, char c) {
|
|
|
|
|
|
|
|
|
|
if (c)
|
|
|
|
|
while (*s == c)
|
|
|
|
|
s++;
|
|
|
|
|
|
|
|
|
|
return s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline char *rtrim(char *s, char c) {
|
|
|
|
|
|
|
|
|
|
char *p = s + strlen(s);
|
|
|
|
|
|
|
|
|
|
while (p-- > s)
|
|
|
|
|
if (*p == c)
|
|
|
|
|
*p = '\0';
|
|
|
|
|
else
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
return s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline char *alltrim(char *s, char c) {
|
|
|
|
|
|
|
|
|
|
rtrim(s, c);
|
|
|
|
|
|
|
|
|
|
return ltrim(s, c);
|
|
|
|
|
}
|
|
|
|
|
|
2007-10-25 04:34:16 -04:00
|
|
|
/* This function converts the time_t value <now> into a broken out struct tm
|
|
|
|
|
* which must be allocated by the caller. It is highly recommended to use this
|
2020-03-10 03:06:11 -04:00
|
|
|
* function instead of localtime() because that one requires a time_t* which
|
2007-10-25 04:34:16 -04:00
|
|
|
* is not always compatible with tv_sec depending on OS/hardware combinations.
|
|
|
|
|
*/
|
|
|
|
|
static inline void get_localtime(const time_t now, struct tm *tm)
|
|
|
|
|
{
|
|
|
|
|
localtime_r(&now, tm);
|
|
|
|
|
}
|
|
|
|
|
|
2009-06-30 12:26:00 -04:00
|
|
|
/* This function converts the time_t value <now> into a broken out struct tm
|
|
|
|
|
* which must be allocated by the caller. It is highly recommended to use this
|
2020-03-10 03:06:11 -04:00
|
|
|
* function instead of gmtime() because that one requires a time_t* which
|
2009-06-30 12:26:00 -04:00
|
|
|
* is not always compatible with tv_sec depending on OS/hardware combinations.
|
|
|
|
|
*/
|
|
|
|
|
static inline void get_gmtime(const time_t now, struct tm *tm)
|
|
|
|
|
{
|
|
|
|
|
gmtime_r(&now, tm);
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-19 13:05:29 -04:00
|
|
|
/* Counts a number of elapsed days since 01/01/0000 based solely on elapsed
|
|
|
|
|
* years and assuming the regular rule for leap years applies. It's fake but
|
|
|
|
|
* serves as a temporary origin. It's worth remembering that it's the first
|
|
|
|
|
* year of each period that is leap and not the last one, so for instance year
|
|
|
|
|
* 1 sees 366 days since year 0 was leap. For this reason we have to apply
|
2020-03-10 03:06:11 -04:00
|
|
|
* modular arithmetic which is why we offset the year by 399 before
|
2017-07-19 13:05:29 -04:00
|
|
|
* subtracting the excess at the end. No overflow here before ~11.7 million
|
|
|
|
|
* years.
|
|
|
|
|
*/
|
|
|
|
|
static inline unsigned int days_since_zero(unsigned int y)
|
|
|
|
|
{
|
|
|
|
|
return y * 365 + (y + 399) / 4 - (y + 399) / 100 + (y + 399) / 400
|
|
|
|
|
- 399 / 4 + 399 / 100;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Returns the number of seconds since 01/01/1970 0:0:0 GMT for GMT date <tm>.
|
|
|
|
|
* It is meant as a portable replacement for timegm() for use with valid inputs.
|
|
|
|
|
* Returns undefined results for invalid dates (eg: months out of range 0..11).
|
|
|
|
|
*/
|
|
|
|
|
extern time_t my_timegm(const struct tm *tm);
|
|
|
|
|
|
2007-12-02 16:00:35 -05:00
|
|
|
/* This function parses a time value optionally followed by a unit suffix among
|
|
|
|
|
* "d", "h", "m", "s", "ms" or "us". It converts the value into the unit
|
|
|
|
|
* expected by the caller. The computation does its best to avoid overflows.
|
|
|
|
|
* The value is returned in <ret> if everything is fine, and a NULL is returned
|
|
|
|
|
* by the function. In case of error, a pointer to the error is returned and
|
|
|
|
|
* <ret> is left untouched.
|
|
|
|
|
*/
|
|
|
|
|
extern const char *parse_time_err(const char *text, unsigned *ret, unsigned unit_flags);
|
2024-11-19 03:15:19 -05:00
|
|
|
extern const char *parse_size_ui(const char *text, unsigned *ret);
|
|
|
|
|
extern const char *parse_size_ull(const char *text, ullong *ret);
|
|
|
|
|
|
|
|
|
|
/* Parse a size from <_test> into <_ret> which must be compatible with a
|
|
|
|
|
* uint or ullong. The return value is a pointer to the first unparsable
|
|
|
|
|
* character (if any) or NULL if everything's OK.
|
|
|
|
|
*/
|
|
|
|
|
#define parse_size_err(_text, _ret) ({ \
|
|
|
|
|
const char *_err; \
|
|
|
|
|
if (sizeof(*(_ret)) > sizeof(int)) { \
|
|
|
|
|
unsigned long long _tmp; \
|
|
|
|
|
_err = parse_size_ull(_text, &_tmp); \
|
|
|
|
|
*_ret = _tmp; \
|
|
|
|
|
} else { \
|
|
|
|
|
unsigned int _tmp; \
|
|
|
|
|
_err = parse_size_ui(_text, &_tmp); \
|
|
|
|
|
*_ret = _tmp; \
|
|
|
|
|
} \
|
|
|
|
|
_err; \
|
|
|
|
|
})
|
2007-12-02 16:00:35 -05:00
|
|
|
|
2013-12-03 11:50:47 -05:00
|
|
|
/*
|
|
|
|
|
* Parse binary string written in hexadecimal (source) and store the decoded
|
2020-03-10 03:06:11 -04:00
|
|
|
* result into binstr and set binstrlen to the length of binstr. Memory for
|
2013-12-03 11:50:47 -05:00
|
|
|
* binstr is allocated by the function. In case of error, returns 0 with an
|
|
|
|
|
* error message in err.
|
|
|
|
|
*/
|
|
|
|
|
int parse_binary(const char *source, char **binstr, int *binstrlen, char **err);
|
|
|
|
|
|
2009-05-10 09:41:18 -04:00
|
|
|
/* copies at most <n> characters from <src> and always terminates with '\0' */
|
2025-04-29 23:15:22 -04:00
|
|
|
char *my_strndup(const char *src, size_t n);
|
2009-05-10 09:41:18 -04:00
|
|
|
|
2013-10-06 17:24:13 -04:00
|
|
|
/*
|
|
|
|
|
* search needle in haystack
|
|
|
|
|
* returns the pointer if found, returns NULL otherwise
|
|
|
|
|
*/
|
|
|
|
|
const void *my_memmem(const void *, size_t, const void *, size_t);
|
|
|
|
|
|
2020-06-21 12:42:57 -04:00
|
|
|
/* get length of the initial segment consisting entirely of bytes within a given
|
2020-04-15 04:23:01 -04:00
|
|
|
* mask
|
|
|
|
|
*/
|
|
|
|
|
size_t my_memspn(const void *, size_t, const void *, size_t);
|
|
|
|
|
|
2020-06-21 12:42:57 -04:00
|
|
|
/* get length of the initial segment consisting entirely of bytes not within a
|
2020-04-15 04:23:01 -04:00
|
|
|
* given mask
|
|
|
|
|
*/
|
|
|
|
|
size_t my_memcspn(const void *, size_t, const void *, size_t);
|
|
|
|
|
|
2009-10-04 16:48:42 -04:00
|
|
|
/* This function returns the first unused key greater than or equal to <key> in
|
|
|
|
|
* ID tree <root>. Zero is returned if no place is found.
|
|
|
|
|
*/
|
|
|
|
|
unsigned int get_next_id(struct eb_root *root, unsigned int key);
|
|
|
|
|
|
2017-11-15 12:51:29 -05:00
|
|
|
/* dump the full tree to <file> in DOT format for debugging purposes. Will
|
|
|
|
|
* optionally highlight node <subj> if found, depending on operation <op> :
|
|
|
|
|
* 0 : nothing
|
|
|
|
|
* >0 : insertion, node/leaf are surrounded in red
|
|
|
|
|
* <0 : removal, node/leaf are dashed with no background
|
|
|
|
|
* Will optionally add "desc" as a label on the graph if set and non-null.
|
|
|
|
|
*/
|
|
|
|
|
void eb32sc_to_file(FILE *file, struct eb_root *root, const struct eb32sc_node *subj,
|
|
|
|
|
int op, const char *desc);
|
2017-11-15 09:04:05 -05:00
|
|
|
|
2022-08-01 05:55:57 -04:00
|
|
|
/* same but for ebmb */
|
|
|
|
|
void ebmb_to_file(FILE *file, struct eb_root *root, const struct ebmb_node *subj,
|
|
|
|
|
int op, const char *desc);
|
|
|
|
|
|
2010-01-18 09:05:57 -05:00
|
|
|
/* This function compares a sample word possibly followed by blanks to another
|
|
|
|
|
* clean word. The compare is case-insensitive. 1 is returned if both are equal,
|
|
|
|
|
* otherwise zero. This intends to be used when checking HTTP headers for some
|
|
|
|
|
* values.
|
|
|
|
|
*/
|
|
|
|
|
int word_match(const char *sample, int slen, const char *word, int wlen);
|
|
|
|
|
|
2010-06-06 07:22:23 -04:00
|
|
|
/* Convert a fixed-length string to an IP address. Returns 0 in case of error,
|
|
|
|
|
* or the number of chars read in case of success.
|
|
|
|
|
*/
|
|
|
|
|
int buf2ip(const char *buf, size_t len, struct in_addr *dst);
|
2013-11-22 10:16:59 -05:00
|
|
|
int buf2ip6(const char *buf, size_t len, struct in6_addr *dst);
|
2010-06-06 07:22:23 -04:00
|
|
|
|
2010-06-14 13:09:21 -04:00
|
|
|
/* To be used to quote config arg positions. Returns the string at <ptr>
|
|
|
|
|
* surrounded by simple quotes if <ptr> is valid and non-empty, or "end of line"
|
|
|
|
|
* if ptr is NULL or empty. The string is locally allocated.
|
|
|
|
|
*/
|
|
|
|
|
const char *quote_arg(const char *ptr);
|
|
|
|
|
|
2010-07-18 04:40:48 -04:00
|
|
|
/* returns an operator among STD_OP_* for string <str> or < 0 if unknown */
|
|
|
|
|
int get_std_op(const char *str);
|
|
|
|
|
|
2012-10-26 13:47:23 -04:00
|
|
|
/* sets the address family to AF_UNSPEC so that is_addr() does not match */
|
|
|
|
|
static inline void clear_addr(struct sockaddr_storage *addr)
|
|
|
|
|
{
|
|
|
|
|
addr->ss_family = AF_UNSPEC;
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-10 16:26:24 -05:00
|
|
|
/* returns non-zero if addr has a valid and non-null IPv4 or IPv6 address,
|
|
|
|
|
* otherwise zero.
|
|
|
|
|
*/
|
2014-05-09 16:40:55 -04:00
|
|
|
static inline int is_inet_addr(const struct sockaddr_storage *addr)
|
2011-03-10 16:26:24 -05:00
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
switch (addr->ss_family) {
|
|
|
|
|
case AF_INET:
|
2011-03-22 06:39:41 -04:00
|
|
|
return *(int *)&((struct sockaddr_in *)addr)->sin_addr;
|
2011-03-10 16:26:24 -05:00
|
|
|
case AF_INET6:
|
|
|
|
|
for (i = 0; i < sizeof(struct in6_addr) / sizeof(int); i++)
|
|
|
|
|
if (((int *)&((struct sockaddr_in6 *)addr)->sin6_addr)[i] != 0)
|
|
|
|
|
return ((int *)&((struct sockaddr_in6 *)addr)->sin6_addr)[i];
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2014-05-09 16:40:55 -04:00
|
|
|
|
|
|
|
|
/* returns non-zero if addr has a valid and non-null IPv4 or IPv6 address,
|
|
|
|
|
* or is a unix address, otherwise returns zero.
|
|
|
|
|
*/
|
|
|
|
|
static inline int is_addr(const struct sockaddr_storage *addr)
|
|
|
|
|
{
|
MEDIUM: protocol: make abns a custom unix socket address family
This is a pre-requisite to adding the abnsz socket address family:
in this patch we make use of protocol API rework started by 732913f
("MINOR: protocol: properly assign the sock_domain and sock_family") in
order to implement a dedicated address family for ABNS sockets (based on
UNIX parent family).
Thanks to this, it will become trivial to implement a new ABNSZ (for abns
zero) family which is essentially the same as ABNS but with a slight
difference when it comes to path handling (ABNS uses the whole sun_path
length, while ABNSZ's path is zero terminated and evaluation stops at 0)
It was verified that this patch doesn't break reg-tests and behaves
properly (tests performed on the CLI with show sess and show fd).
Anywhere relevant, AF_CUST_ABNS is handled alongside AF_UNIX. If no
distinction needs to be made, real_family() is used to fetch the proper
real family type to handle it properly.
Both stream and dgram were converted, so no functional change should be
expected for this "internal" rework, except that proto will be displayed
as "abns_{stream,dgram}" instead of "unix_{stream,dgram}".
Before ("show sess" output):
0x64c35528aab0: proto=unix_stream src=unix:1 fe=GLOBAL be=<NONE> srv=<none> ts=00 epoch=0 age=0s calls=1 rate=0 cpu=0 lat=0 rq[f=848000h,i=0,an=00h,ax=] rp[f=80008000h,i=0,an=00h,ax=] scf=[8,0h,fd=21,rex=10s,wex=] scb=[8,1h,fd=-1,rex=,wex=] exp=10s rc=0 c_exp=
After:
0x619da7ad74c0: proto=abns_stream src=unix:1 fe=GLOBAL be=<NONE> srv=<none> ts=00 epoch=0 age=0s calls=1 rate=0 cpu=0 lat=0 rq[f=848000h,i=0,an=00h,ax=] rp[f=80008000h,i=0,an=00h,ax=] scf=[8,0h,fd=22,rex=10s,wex=] scb=[8,1h,fd=-1,rex=,wex=] exp=10s rc=0 c_exp=
Co-authored-by: Aurelien DARRAGON <adarragon@haproxy.com>
2024-08-09 12:48:14 -04:00
|
|
|
/* WT: ideally we should use real_family(addr->ss_family) here, but we
|
|
|
|
|
* have so few custom addresses that it's simple enough to test them all.
|
|
|
|
|
*/
|
2024-08-09 15:12:23 -04:00
|
|
|
if (addr->ss_family == AF_UNIX || addr->ss_family == AF_CUST_ABNS ||
|
|
|
|
|
addr->ss_family == AF_CUST_ABNSZ || addr->ss_family == AF_CUST_SOCKPAIR)
|
2014-05-09 16:40:55 -04:00
|
|
|
return 1;
|
|
|
|
|
else
|
|
|
|
|
return is_inet_addr(addr);
|
|
|
|
|
}
|
2011-03-10 16:26:24 -05:00
|
|
|
|
2011-03-24 07:23:00 -04:00
|
|
|
/* returns port in network byte order */
|
2021-10-22 09:32:48 -04:00
|
|
|
static inline int get_net_port(const struct sockaddr_storage *addr)
|
2011-03-24 07:23:00 -04:00
|
|
|
{
|
|
|
|
|
switch (addr->ss_family) {
|
|
|
|
|
case AF_INET:
|
|
|
|
|
return ((struct sockaddr_in *)addr)->sin_port;
|
|
|
|
|
case AF_INET6:
|
|
|
|
|
return ((struct sockaddr_in6 *)addr)->sin6_port;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* returns port in host byte order */
|
2021-10-22 09:32:48 -04:00
|
|
|
static inline int get_host_port(const struct sockaddr_storage *addr)
|
2011-03-24 07:23:00 -04:00
|
|
|
{
|
|
|
|
|
switch (addr->ss_family) {
|
|
|
|
|
case AF_INET:
|
|
|
|
|
return ntohs(((struct sockaddr_in *)addr)->sin_port);
|
|
|
|
|
case AF_INET6:
|
|
|
|
|
return ntohs(((struct sockaddr_in6 *)addr)->sin6_port);
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-05 10:56:50 -04:00
|
|
|
/* returns address len for <addr>'s family, 0 for unknown families */
|
|
|
|
|
static inline int get_addr_len(const struct sockaddr_storage *addr)
|
|
|
|
|
{
|
|
|
|
|
switch (addr->ss_family) {
|
|
|
|
|
case AF_INET:
|
|
|
|
|
return sizeof(struct sockaddr_in);
|
|
|
|
|
case AF_INET6:
|
|
|
|
|
return sizeof(struct sockaddr_in6);
|
|
|
|
|
case AF_UNIX:
|
MEDIUM: protocol: make abns a custom unix socket address family
This is a pre-requisite to adding the abnsz socket address family:
in this patch we make use of protocol API rework started by 732913f
("MINOR: protocol: properly assign the sock_domain and sock_family") in
order to implement a dedicated address family for ABNS sockets (based on
UNIX parent family).
Thanks to this, it will become trivial to implement a new ABNSZ (for abns
zero) family which is essentially the same as ABNS but with a slight
difference when it comes to path handling (ABNS uses the whole sun_path
length, while ABNSZ's path is zero terminated and evaluation stops at 0)
It was verified that this patch doesn't break reg-tests and behaves
properly (tests performed on the CLI with show sess and show fd).
Anywhere relevant, AF_CUST_ABNS is handled alongside AF_UNIX. If no
distinction needs to be made, real_family() is used to fetch the proper
real family type to handle it properly.
Both stream and dgram were converted, so no functional change should be
expected for this "internal" rework, except that proto will be displayed
as "abns_{stream,dgram}" instead of "unix_{stream,dgram}".
Before ("show sess" output):
0x64c35528aab0: proto=unix_stream src=unix:1 fe=GLOBAL be=<NONE> srv=<none> ts=00 epoch=0 age=0s calls=1 rate=0 cpu=0 lat=0 rq[f=848000h,i=0,an=00h,ax=] rp[f=80008000h,i=0,an=00h,ax=] scf=[8,0h,fd=21,rex=10s,wex=] scb=[8,1h,fd=-1,rex=,wex=] exp=10s rc=0 c_exp=
After:
0x619da7ad74c0: proto=abns_stream src=unix:1 fe=GLOBAL be=<NONE> srv=<none> ts=00 epoch=0 age=0s calls=1 rate=0 cpu=0 lat=0 rq[f=848000h,i=0,an=00h,ax=] rp[f=80008000h,i=0,an=00h,ax=] scf=[8,0h,fd=22,rex=10s,wex=] scb=[8,1h,fd=-1,rex=,wex=] exp=10s rc=0 c_exp=
Co-authored-by: Aurelien DARRAGON <adarragon@haproxy.com>
2024-08-09 12:48:14 -04:00
|
|
|
case AF_CUST_ABNS:
|
2011-04-05 10:56:50 -04:00
|
|
|
return sizeof(struct sockaddr_un);
|
2024-10-28 11:23:31 -04:00
|
|
|
case AF_CUST_ABNSZ:
|
|
|
|
|
{
|
|
|
|
|
const struct sockaddr_un *un = (struct sockaddr_un *)addr;
|
|
|
|
|
|
|
|
|
|
/* stop at first NULL-byte */
|
|
|
|
|
return offsetof(struct sockaddr_un, sun_path) + 1 +
|
|
|
|
|
strnlen2(un->sun_path + 1, sizeof(un->sun_path) - 1);
|
|
|
|
|
}
|
2011-04-05 10:56:50 -04:00
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-24 07:23:00 -04:00
|
|
|
/* set port in host byte order */
|
|
|
|
|
static inline int set_net_port(struct sockaddr_storage *addr, int port)
|
|
|
|
|
{
|
|
|
|
|
switch (addr->ss_family) {
|
|
|
|
|
case AF_INET:
|
|
|
|
|
((struct sockaddr_in *)addr)->sin_port = port;
|
2018-09-20 04:48:35 -04:00
|
|
|
break;
|
2011-03-24 07:23:00 -04:00
|
|
|
case AF_INET6:
|
|
|
|
|
((struct sockaddr_in6 *)addr)->sin6_port = port;
|
2018-09-20 04:48:35 -04:00
|
|
|
break;
|
2011-03-24 07:23:00 -04:00
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* set port in network byte order */
|
|
|
|
|
static inline int set_host_port(struct sockaddr_storage *addr, int port)
|
|
|
|
|
{
|
|
|
|
|
switch (addr->ss_family) {
|
|
|
|
|
case AF_INET:
|
|
|
|
|
((struct sockaddr_in *)addr)->sin_port = htons(port);
|
2018-09-20 04:48:35 -04:00
|
|
|
break;
|
2011-03-24 07:23:00 -04:00
|
|
|
case AF_INET6:
|
|
|
|
|
((struct sockaddr_in6 *)addr)->sin6_port = htons(port);
|
2018-09-20 04:48:35 -04:00
|
|
|
break;
|
2011-03-24 07:23:00 -04:00
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-22 08:21:16 -04:00
|
|
|
/* Returns true if <addr> port is forbidden as client source using <proto>. */
|
|
|
|
|
static inline int port_is_restricted(const struct sockaddr_storage *addr,
|
|
|
|
|
enum ha_proto proto)
|
|
|
|
|
{
|
|
|
|
|
const uint16_t port = get_host_port(addr);
|
|
|
|
|
|
|
|
|
|
BUG_ON_HOT(proto != HA_PROTO_TCP && proto != HA_PROTO_QUIC);
|
|
|
|
|
|
|
|
|
|
/* RFC 6335 6. Port Number Ranges */
|
|
|
|
|
if (unlikely(port < 1024 && port > 0))
|
|
|
|
|
return !(global.clt_privileged_ports & proto);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-17 11:12:14 -05:00
|
|
|
/* Convert mask from bit length form to in_addr form.
|
|
|
|
|
* This function never fails.
|
|
|
|
|
*/
|
|
|
|
|
void len2mask4(int len, struct in_addr *addr);
|
|
|
|
|
|
|
|
|
|
/* Convert mask from bit length form to in6_addr form.
|
|
|
|
|
* This function never fails.
|
|
|
|
|
*/
|
|
|
|
|
void len2mask6(int len, struct in6_addr *addr);
|
|
|
|
|
|
2011-03-24 06:09:31 -04:00
|
|
|
/* Return true if IPv4 address is part of the network */
|
2016-07-13 05:59:39 -04:00
|
|
|
extern int in_net_ipv4(const void *addr, const struct in_addr *mask, const struct in_addr *net);
|
2011-03-24 06:09:31 -04:00
|
|
|
|
|
|
|
|
/* Return true if IPv6 address is part of the network */
|
2016-07-13 05:59:39 -04:00
|
|
|
extern int in_net_ipv6(const void *addr, const struct in6_addr *mask, const struct in6_addr *net);
|
2011-03-24 06:09:31 -04:00
|
|
|
|
2018-11-15 14:58:28 -05:00
|
|
|
/* Map IPv4 address on IPv6 address, as specified in RFC 3513. */
|
2011-03-24 06:09:31 -04:00
|
|
|
extern void v4tov6(struct in6_addr *sin6_addr, struct in_addr *sin_addr);
|
|
|
|
|
|
2018-11-15 14:58:28 -05:00
|
|
|
/* Map IPv6 address on IPv4 address, as specified in RFC 3513.
|
2011-03-24 06:09:31 -04:00
|
|
|
* Return true if conversion is possible and false otherwise.
|
|
|
|
|
*/
|
|
|
|
|
extern int v6tov4(struct in_addr *sin_addr, struct in6_addr *sin6_addr);
|
|
|
|
|
|
2022-12-01 11:46:45 -05:00
|
|
|
/* compare two struct sockaddr_storage, including port if <check_port> is true,
|
|
|
|
|
* and return:
|
2016-01-23 17:39:12 -05:00
|
|
|
* 0 (true) if the addr is the same in both
|
|
|
|
|
* 1 (false) if the addr is not the same in both
|
2022-12-01 11:46:45 -05:00
|
|
|
* -1 (unable) if one of the addr is not AF_INET*
|
2016-01-23 17:39:12 -05:00
|
|
|
*/
|
2023-11-13 08:12:04 -05:00
|
|
|
int ipcmp(const struct sockaddr_storage *ss1, const struct sockaddr_storage *ss2, int check_port);
|
2016-01-23 17:39:12 -05:00
|
|
|
|
2021-02-26 03:12:50 -05:00
|
|
|
/* compare a struct sockaddr_storage to a struct net_addr and return :
|
|
|
|
|
* 0 (true) if <addr> is matching <net>
|
|
|
|
|
* 1 (false) if <addr> is not matching <net>
|
|
|
|
|
* -1 (unable) if <addr> or <net> is not AF_INET*
|
|
|
|
|
*/
|
|
|
|
|
int ipcmp2net(const struct sockaddr_storage *addr, const struct net_addr *net);
|
|
|
|
|
|
2016-01-30 18:27:17 -05:00
|
|
|
/* copy ip from <source> into <dest>
|
|
|
|
|
* the caller must clear <dest> before calling.
|
|
|
|
|
* Returns a pointer to the destination
|
|
|
|
|
*/
|
2023-11-13 08:12:04 -05:00
|
|
|
struct sockaddr_storage *ipcpy(const struct sockaddr_storage *source, struct sockaddr_storage *dest);
|
2016-01-30 18:27:17 -05:00
|
|
|
|
2024-08-30 07:56:15 -04:00
|
|
|
/* Copy only the IP address from <saddr> socket address data into <buf> buffer. *
|
|
|
|
|
* Return the number of bytes copied.
|
|
|
|
|
*/
|
|
|
|
|
size_t ipaddrcpy(unsigned char *buf, const struct sockaddr_storage *saddr);
|
|
|
|
|
|
2012-02-06 12:15:57 -05:00
|
|
|
char *human_time(int t, short hz_div);
|
|
|
|
|
|
|
|
|
|
extern const char *monthname[];
|
|
|
|
|
|
|
|
|
|
/* date2str_log: write a date in the format :
|
|
|
|
|
* sprintf(str, "%02d/%s/%04d:%02d:%02d:%02d.%03d",
|
|
|
|
|
* tm.tm_mday, monthname[tm.tm_mon], tm.tm_year+1900,
|
|
|
|
|
* tm.tm_hour, tm.tm_min, tm.tm_sec, (int)date.tv_usec/1000);
|
|
|
|
|
*
|
|
|
|
|
* without using sprintf. return a pointer to the last char written (\0) or
|
|
|
|
|
* NULL if there isn't enough space.
|
|
|
|
|
*/
|
2018-09-04 13:08:48 -04:00
|
|
|
char *date2str_log(char *dest, const struct tm *tm, const struct timeval *date, size_t size);
|
2012-02-06 12:15:57 -05:00
|
|
|
|
2016-03-27 05:08:03 -04:00
|
|
|
/* Return the GMT offset for a specific local time.
|
2016-03-26 21:04:16 -04:00
|
|
|
* Both t and tm must represent the same time.
|
2016-03-27 05:08:03 -04:00
|
|
|
* The string returned has the same format as returned by strftime(... "%z", tm).
|
|
|
|
|
* Offsets are kept in an internal cache for better performances.
|
|
|
|
|
*/
|
2016-03-26 21:04:16 -04:00
|
|
|
const char *get_gmt_offset(time_t t, struct tm *tm);
|
2016-03-27 05:08:03 -04:00
|
|
|
|
2012-02-06 12:15:57 -05:00
|
|
|
/* gmt2str_log: write a date in the format :
|
|
|
|
|
* "%02d/%s/%04d:%02d:%02d:%02d +0000" without using snprintf
|
|
|
|
|
* return a pointer to the last char written (\0) or
|
|
|
|
|
* NULL if there isn't enough space.
|
|
|
|
|
*/
|
|
|
|
|
char *gmt2str_log(char *dst, struct tm *tm, size_t size);
|
|
|
|
|
|
2012-10-18 22:36:09 -04:00
|
|
|
/* localdate2str_log: write a date in the format :
|
|
|
|
|
* "%02d/%s/%04d:%02d:%02d:%02d +0000(local timezone)" without using snprintf
|
2016-03-26 21:04:16 -04:00
|
|
|
* Both t and tm must represent the same time.
|
2012-10-18 22:36:09 -04:00
|
|
|
* return a pointer to the last char written (\0) or
|
|
|
|
|
* NULL if there isn't enough space.
|
|
|
|
|
*/
|
2016-03-26 21:04:16 -04:00
|
|
|
char *localdate2str_log(char *dst, time_t t, struct tm *tm, size_t size);
|
2012-10-18 22:36:09 -04:00
|
|
|
|
2016-01-20 12:49:45 -05:00
|
|
|
/* These 3 functions parses date string and fills the
|
2020-03-10 03:06:11 -04:00
|
|
|
* corresponding broken-down time in <tm>. In success case,
|
2016-01-20 12:49:45 -05:00
|
|
|
* it returns 1, otherwise, it returns 0.
|
|
|
|
|
*/
|
|
|
|
|
int parse_http_date(const char *date, int len, struct tm *tm);
|
|
|
|
|
int parse_imf_date(const char *date, int len, struct tm *tm);
|
|
|
|
|
int parse_rfc850_date(const char *date, int len, struct tm *tm);
|
|
|
|
|
int parse_asctime_date(const char *date, int len, struct tm *tm);
|
2021-01-29 04:47:52 -05:00
|
|
|
int print_time_short(struct buffer *out, const char *pfx, uint64_t ns, const char *sfx);
|
2016-01-20 12:49:45 -05:00
|
|
|
|
2012-04-27 05:16:50 -04:00
|
|
|
/* Dynamically allocates a string of the proper length to hold the formatted
|
|
|
|
|
* output. NULL is returned on error. The caller is responsible for freeing the
|
|
|
|
|
* memory area using free(). The resulting string is returned in <out> if the
|
|
|
|
|
* pointer is not NULL. A previous version of <out> might be used to build the
|
|
|
|
|
* new string, and it will be freed before returning if it is not NULL, which
|
|
|
|
|
* makes it possible to build complex strings from iterative calls without
|
|
|
|
|
* having to care about freeing intermediate values, as in the example below :
|
|
|
|
|
*
|
|
|
|
|
* memprintf(&err, "invalid argument: '%s'", arg);
|
|
|
|
|
* ...
|
|
|
|
|
* memprintf(&err, "parser said : <%s>\n", *err);
|
|
|
|
|
* ...
|
|
|
|
|
* free(*err);
|
|
|
|
|
*
|
|
|
|
|
* This means that <err> must be initialized to NULL before first invocation.
|
|
|
|
|
* The return value also holds the allocated string, which eases error checking
|
|
|
|
|
* and immediate consumption. If the output pointer is not used, NULL must be
|
2012-09-20 13:43:14 -04:00
|
|
|
* passed instead and it will be ignored. The returned message will then also
|
|
|
|
|
* be NULL so that the caller does not have to bother with freeing anything.
|
2012-04-27 05:16:50 -04:00
|
|
|
*
|
|
|
|
|
* It is also convenient to use it without any free except the last one :
|
|
|
|
|
* err = NULL;
|
|
|
|
|
* if (!fct1(err)) report(*err);
|
|
|
|
|
* if (!fct2(err)) report(*err);
|
|
|
|
|
* if (!fct3(err)) report(*err);
|
|
|
|
|
* free(*err);
|
2017-10-24 05:25:33 -04:00
|
|
|
*
|
|
|
|
|
* memprintf relies on memvprintf. This last version can be called from any
|
|
|
|
|
* function with variadic arguments.
|
2012-04-27 05:16:50 -04:00
|
|
|
*/
|
2017-10-24 05:25:33 -04:00
|
|
|
char *memvprintf(char **out, const char *format, va_list args)
|
|
|
|
|
__attribute__ ((format(printf, 2, 0)));
|
|
|
|
|
|
2012-04-27 05:16:50 -04:00
|
|
|
char *memprintf(char **out, const char *format, ...)
|
|
|
|
|
__attribute__ ((format(printf, 2, 3)));
|
|
|
|
|
|
2012-09-14 05:40:36 -04:00
|
|
|
/* Used to add <level> spaces before each line of <out>, unless there is only one line.
|
|
|
|
|
* The input argument is automatically freed and reassigned. The result will have to be
|
|
|
|
|
* freed by the caller.
|
|
|
|
|
* Example of use :
|
|
|
|
|
* parse(cmd, &err); (callee: memprintf(&err, ...))
|
|
|
|
|
* fprintf(stderr, "Parser said: %s\n", indent_error(&err));
|
|
|
|
|
* free(err);
|
|
|
|
|
*/
|
|
|
|
|
char *indent_msg(char **out, int level);
|
2019-08-21 07:17:37 -04:00
|
|
|
int append_prefixed_str(struct buffer *out, const char *in, const char *pfx, char eol, int first);
|
2012-05-12 18:21:17 -04:00
|
|
|
|
2019-03-29 13:49:09 -04:00
|
|
|
/* removes environment variable <name> from the environment as found in
|
|
|
|
|
* environ. This is only provided as an alternative for systems without
|
|
|
|
|
* unsetenv() (old Solaris and AIX versions). THIS IS NOT THREAD SAFE.
|
2020-03-10 03:06:11 -04:00
|
|
|
* The principle is to scan environ for each occurrence of variable name
|
2019-03-29 13:49:09 -04:00
|
|
|
* <name> and to replace the matching pointers with the last pointer of
|
|
|
|
|
* the array (since variables are not ordered).
|
|
|
|
|
* It always returns 0 (success).
|
|
|
|
|
*/
|
|
|
|
|
int my_unsetenv(const char *name);
|
|
|
|
|
|
2013-03-10 20:20:04 -04:00
|
|
|
/* Convert occurrences of environment variables in the input string to their
|
|
|
|
|
* corresponding value. A variable is identified as a series of alphanumeric
|
|
|
|
|
* characters or underscores following a '$' sign. The <in> string must be
|
|
|
|
|
* free()able. NULL returns NULL. The resulting string might be reallocated if
|
|
|
|
|
* some expansion is made.
|
|
|
|
|
*/
|
|
|
|
|
char *env_expand(char *in);
|
2025-06-24 11:18:52 -04:00
|
|
|
struct ist env_suggest(struct ist word);
|
2025-01-06 13:34:41 -05:00
|
|
|
int is_path_mode(mode_t mode, const char *path_fmt, ...);
|
|
|
|
|
int is_file_present(const char *path_fmt, ...);
|
|
|
|
|
int is_dir_present(const char *path_fmt, ...);
|
2021-06-05 18:50:21 -04:00
|
|
|
uint32_t parse_line(char *in, char *out, size_t *outlen, char **args, int *nbargs, uint32_t opts, const char **errptr);
|
2023-07-06 12:31:53 -04:00
|
|
|
ssize_t read_line_to_trash(const char *path_fmt, ...);
|
2020-06-25 03:15:40 -04:00
|
|
|
size_t sanitize_for_printing(char *line, size_t pos, size_t width);
|
2025-06-24 11:14:47 -04:00
|
|
|
void update_word_fingerprint_with_len(uint8_t *fp, struct ist word);
|
2021-03-12 12:59:31 -05:00
|
|
|
void update_word_fingerprint(uint8_t *fp, const char *word);
|
2025-06-24 11:14:47 -04:00
|
|
|
void make_word_fingerprint_with_len(uint8_t *fp, struct ist word);
|
2021-03-12 03:01:52 -05:00
|
|
|
void make_word_fingerprint(uint8_t *fp, const char *word);
|
|
|
|
|
int word_fingerprint_distance(const uint8_t *fp1, const uint8_t *fp2);
|
2013-03-10 20:20:04 -04:00
|
|
|
|
2012-05-12 18:21:17 -04:00
|
|
|
/* debugging macro to emit messages using write() on fd #-1 so that strace sees
|
2024-12-09 11:40:51 -05:00
|
|
|
* them. It relies on variadic macros with optional arguments so that any
|
|
|
|
|
* number of argument is accepted. If at least one argument is passed, the
|
|
|
|
|
* first one is a format string and the other ones are the arguments, exactly
|
|
|
|
|
* like printf(). The macro always prepends the function name and the location
|
|
|
|
|
* as file:line between square brackets on any line. If no format string is
|
|
|
|
|
* passed, then "\n" is used. Otherwise the caller has to deal with \n itself
|
|
|
|
|
* (format or data).
|
|
|
|
|
*/
|
|
|
|
|
#define fddebug(...) __fddebug(__VA_ARGS__)
|
|
|
|
|
#define _fddebug(fmt, msg...) __fddebug("" ##fmt, ##msg)
|
|
|
|
|
#define __fddebug(fmt, msg...) do { \
|
|
|
|
|
char *_m = NULL; \
|
|
|
|
|
memprintf(&_m, \
|
|
|
|
|
(""fmt)[0] ? \
|
|
|
|
|
("[%s@%s:%d] " fmt) : \
|
|
|
|
|
("[%s@%s:%d]\n"), __func__, \
|
|
|
|
|
__FILE__, __LINE__, ##msg); \
|
|
|
|
|
if (_m) \
|
|
|
|
|
write(-1, _m, strlen(_m)); \
|
|
|
|
|
free(_m); \
|
|
|
|
|
} while (0)
|
2012-05-12 18:21:17 -04:00
|
|
|
|
2016-12-04 18:10:57 -05:00
|
|
|
/* displays a <len> long memory block at <buf>, assuming first byte of <buf>
|
2017-04-27 12:03:20 -04:00
|
|
|
* has address <baseaddr>. String <pfx> may be placed as a prefix in front of
|
|
|
|
|
* each line. It may be NULL if unused. The output is emitted to file <out>.
|
2016-12-04 18:10:57 -05:00
|
|
|
*/
|
2017-04-27 12:03:20 -04:00
|
|
|
void debug_hexdump(FILE *out, const char *pfx, const char *buf, unsigned int baseaddr, int len);
|
2016-12-04 18:10:57 -05:00
|
|
|
|
2019-08-08 10:53:40 -04:00
|
|
|
/* this is used to emit call traces when building with TRACE=1 */
|
2017-10-24 04:54:08 -04:00
|
|
|
__attribute__((format(printf, 1, 2)))
|
2019-08-08 10:53:40 -04:00
|
|
|
void calltrace(char *fmt, ...);
|
2017-10-24 04:54:08 -04:00
|
|
|
|
2013-04-15 13:27:10 -04:00
|
|
|
/* same as strstr() but case-insensitive */
|
|
|
|
|
const char *strnistr(const char *str1, int len_str1, const char *str2, int len_str2);
|
|
|
|
|
|
2022-03-30 04:02:56 -04:00
|
|
|
int strordered(const char *s1, const char *s2, const char *s3);
|
|
|
|
|
|
2018-09-10 12:41:28 -04:00
|
|
|
/* after increasing a pointer value, it can exceed the first buffer
|
|
|
|
|
* size. This function transform the value of <ptr> according with
|
|
|
|
|
* the expected position. <chunks> is an array of the one or two
|
2018-11-15 14:58:28 -05:00
|
|
|
* available chunks. The first value is the start of the first chunk,
|
2018-09-10 12:41:28 -04:00
|
|
|
* the second value if the end+1 of the first chunks. The third value
|
|
|
|
|
* is NULL or the start of the second chunk and the fourth value is
|
|
|
|
|
* the end+1 of the second chunk. The function returns 1 if does a
|
|
|
|
|
* wrap, else returns 0.
|
|
|
|
|
*/
|
|
|
|
|
static inline int fix_pointer_if_wrap(const char **chunks, const char **ptr)
|
|
|
|
|
{
|
|
|
|
|
if (*ptr < chunks[1])
|
|
|
|
|
return 0;
|
|
|
|
|
if (!chunks[2])
|
|
|
|
|
return 0;
|
|
|
|
|
*ptr = chunks[2] + ( *ptr - chunks[1] );
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
2014-01-28 17:04:39 -05:00
|
|
|
|
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-08-12 04:20:47 -04:00
|
|
|
unsigned char utf8_next(const char *s, int len, unsigned int *c);
|
|
|
|
|
|
|
|
|
|
static inline unsigned char utf8_return_code(unsigned int code)
|
|
|
|
|
{
|
|
|
|
|
return code & 0xf0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline unsigned char utf8_return_length(unsigned char code)
|
|
|
|
|
{
|
|
|
|
|
return code & 0x0f;
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-29 11:13:35 -04:00
|
|
|
/* returns a 64-bit a timestamp with the finest resolution available. The
|
|
|
|
|
* unit is intentionally not specified. It's mostly used to compare dates.
|
|
|
|
|
*/
|
|
|
|
|
#if defined(__i386__) || defined(__x86_64__)
|
|
|
|
|
static inline unsigned long long rdtsc()
|
|
|
|
|
{
|
|
|
|
|
unsigned int a, d;
|
|
|
|
|
asm volatile("rdtsc" : "=a" (a), "=d" (d));
|
|
|
|
|
return a + ((unsigned long long)d << 32);
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
static inline unsigned long long rdtsc()
|
|
|
|
|
{
|
|
|
|
|
struct timeval tv;
|
|
|
|
|
gettimeofday(&tv, NULL);
|
|
|
|
|
return tv.tv_sec * 1000000 + tv.tv_usec;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2016-05-13 17:52:54 -04:00
|
|
|
/* append a copy of string <str> (in a wordlist) at the end of the list <li>
|
|
|
|
|
* On failure : return 0 and <err> filled with an error message.
|
|
|
|
|
* The caller is responsible for freeing the <err> and <str> copy
|
|
|
|
|
* memory area using free()
|
|
|
|
|
*/
|
|
|
|
|
|
2018-07-13 05:56:34 -04:00
|
|
|
int dump_text(struct buffer *out, const char *buf, int bsize);
|
|
|
|
|
int dump_binary(struct buffer *out, const char *buf, int bsize);
|
|
|
|
|
int dump_text_line(struct buffer *out, const char *buf, int bsize, int len,
|
2016-11-22 12:00:20 -05:00
|
|
|
int *line, int ptr);
|
2020-03-03 09:57:10 -05:00
|
|
|
void dump_addr_and_bytes(struct buffer *buf, const char *pfx, const void *addr, int n);
|
2024-04-12 10:18:34 -04:00
|
|
|
void dump_area_with_syms(struct buffer *output, const void *base, const void *addr,
|
|
|
|
|
const void *special, const char *spec_type, const char *spec_name);
|
2019-05-20 10:48:20 -04:00
|
|
|
void dump_hex(struct buffer *out, const char *pfx, const void *buf, int len, int unsafe);
|
|
|
|
|
int may_access(const void *ptr);
|
2021-01-20 08:37:59 -05:00
|
|
|
const void *resolve_sym_name(struct buffer *buf, const char *pfx, const void *addr);
|
2024-11-21 09:15:53 -05:00
|
|
|
const void *resolve_dso_name(struct buffer *buf, const char *pfx, const void *addr);
|
CLEANUP: tree-wide: fix prototypes for functions taking no arguments.
"f(void)" is the correct and preferred form for a function taking no
argument, while some places use the older "f()". These were reported
by clang's -Wmissing-prototypes, for example:
src/cpuset.c:111:5: warning: no previous prototype for function 'ha_cpuset_size' [-Wmissing-prototypes]
int ha_cpuset_size()
include/haproxy/cpuset.h:42:5: note: this declaration is not a prototype; add 'void' to make it a prototype for a zero-parameter function
int ha_cpuset_size();
^
void
This aggregate patch fixes this for the following functions:
ha_backtrace_to_stderr(), ha_cpuset_size(), ha_panic(), ha_random64(),
ha_thread_dump_all_to_trash(), get_exec_path(), check_config_validity(),
mworker_child_nb(), mworker_cli_proxy_(create|stop)(),
mworker_cleantasks(), mworker_cleanlisteners(), mworker_ext_launch_all(),
mworker_reload(), mworker_(env|proc_list)_to_(proc_list|env)(),
mworker_(un|)block_signals(), proxy_adjust_all_maxconn(),
proxy_destroy_all_defaults(), get_tainted(),
pool_total_(allocated|used)(), thread_isolate(_full|)(),
thread(_sync|)_release(), thread_harmless_till_end(),
thread_cpu_mask_forced(), dequeue_all_listeners(), next_timer_expiry(),
wake_expired_tasks(), process_runnable_tasks(), init_acl(),
init_buffer(), (de|)init_log_buffers(), (de|)init_pollers(),
fork_poller(), pool_destroy_all(), pool_evict_from_local_caches(),
pool_total_failures(), dump_pools_to_trash(), cfg_run_diagnostics(),
tv_init_(process|thread)_date(), __signal_process_queue(),
deinit_signals(), haproxy_unblock_signals()
2021-09-12 06:49:33 -04:00
|
|
|
const char *get_exec_path(void);
|
2021-05-05 03:06:21 -04:00
|
|
|
void *get_sym_curr_addr(const char *name);
|
|
|
|
|
void *get_sym_next_addr(const char *name);
|
2021-12-28 03:57:10 -05:00
|
|
|
int dump_libs(struct buffer *output, int with_addr);
|
2016-11-22 12:00:20 -05:00
|
|
|
|
2020-03-04 01:44:06 -05:00
|
|
|
/* Note that this may result in opening libgcc() on first call, so it may need
|
|
|
|
|
* to have been called once before chrooting.
|
|
|
|
|
*/
|
|
|
|
|
static forceinline int my_backtrace(void **buffer, int max)
|
|
|
|
|
{
|
2021-01-22 06:12:29 -05:00
|
|
|
#if !defined(USE_BACKTRACE)
|
|
|
|
|
return 0;
|
|
|
|
|
#elif defined(HA_HAVE_WORKING_BACKTRACE)
|
2020-03-04 01:44:06 -05:00
|
|
|
return backtrace(buffer, max);
|
|
|
|
|
#else
|
|
|
|
|
const struct frame {
|
|
|
|
|
const struct frame *next;
|
|
|
|
|
void *ra;
|
|
|
|
|
} *frame;
|
|
|
|
|
int count;
|
|
|
|
|
|
|
|
|
|
frame = __builtin_frame_address(0);
|
|
|
|
|
for (count = 0; count < max && may_access(frame) && may_access(frame->ra);) {
|
|
|
|
|
buffer[count++] = frame->ra;
|
|
|
|
|
frame = frame->next;
|
|
|
|
|
}
|
|
|
|
|
return count;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-28 16:41:00 -04:00
|
|
|
/* same as realloc() except that ptr is also freed upon failure */
|
|
|
|
|
static inline void *my_realloc2(void *ptr, size_t size)
|
|
|
|
|
{
|
|
|
|
|
void *ret;
|
|
|
|
|
|
|
|
|
|
ret = realloc(ptr, size);
|
|
|
|
|
if (!ret && size)
|
|
|
|
|
free(ptr);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-31 09:26:58 -04:00
|
|
|
/* portable memalign(): tries to accommodate OS specificities, and may fall
|
|
|
|
|
* back to plain malloc() if not supported, meaning that alignment guarantees
|
|
|
|
|
* are only a performance bonus but not granted. The caller is responsible for
|
|
|
|
|
* guaranteeing that the requested alignment is at least sizeof(void*) and a
|
|
|
|
|
* power of two. If uncertain, use ha_aligned_alloc() instead. The pointer
|
|
|
|
|
* needs to be passed to ha_aligned_free() for freeing (due to cygwin). Please
|
|
|
|
|
* use ha_aligned_alloc() instead (which does perform accounting).
|
|
|
|
|
*/
|
|
|
|
|
static inline void *_ha_aligned_alloc(size_t alignment, size_t size)
|
|
|
|
|
{
|
|
|
|
|
/* let's consider that most OSes have posix_memalign() and make the
|
|
|
|
|
* exception for the other ones. This way if an OS fails to build,
|
|
|
|
|
* we'll know about it and handle it as a new exception instead of
|
|
|
|
|
* relying on old fallbacks that may break (e.g. most BSDs have
|
|
|
|
|
* dropped memalign()).
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#if defined(_WIN32)
|
|
|
|
|
/* MINGW (Cygwin) uses _aligned_malloc() */
|
|
|
|
|
return _aligned_malloc(size, alignment);
|
|
|
|
|
#elif _POSIX_VERSION < 200112L || defined(__sun)
|
|
|
|
|
/* Old OSes or Solaris */
|
|
|
|
|
return memalign(alignment, size);
|
|
|
|
|
#else
|
|
|
|
|
void *ret;
|
|
|
|
|
|
|
|
|
|
/* most BSD, Linux since glibc 2.2, Solaris 11 */
|
|
|
|
|
if (posix_memalign(&ret, alignment, size) == 0)
|
|
|
|
|
return ret;
|
|
|
|
|
else
|
|
|
|
|
return NULL;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-11 12:46:28 -04:00
|
|
|
/* Like above but zeroing the area */
|
|
|
|
|
static inline void *_ha_aligned_zalloc(size_t alignment, size_t size)
|
|
|
|
|
{
|
|
|
|
|
void *ret = _ha_aligned_alloc(alignment, size);
|
|
|
|
|
|
|
|
|
|
if (ret)
|
|
|
|
|
memset(ret, 0, size);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-31 09:26:58 -04:00
|
|
|
/* portable memalign(): tries to accommodate OS specificities, and may fall
|
|
|
|
|
* back to plain malloc() if not supported, meaning that alignment guarantees
|
|
|
|
|
* are only a performance bonus but not granted. The size will automatically be
|
|
|
|
|
* rounded up to the next power of two and set to a minimum of sizeof(void*).
|
|
|
|
|
* The checks are cheap and generally optimized away by the compiler since most
|
|
|
|
|
* input arguments are build time constants. The pointer needs to be passed to
|
|
|
|
|
* ha_aligned_free() for freeing (due to cygwin). Please use
|
|
|
|
|
* ha_aligned_alloc_safe() instead (which does perform accounting).
|
|
|
|
|
*/
|
|
|
|
|
static inline void *_ha_aligned_alloc_safe(size_t alignment, size_t size)
|
|
|
|
|
{
|
|
|
|
|
if (unlikely(alignment < sizeof(void*)))
|
|
|
|
|
alignment = sizeof(void*);
|
|
|
|
|
else if (unlikely(alignment & (alignment - 1))) {
|
|
|
|
|
/* not power of two! round up to next power of two by filling
|
|
|
|
|
* all LSB in O(log(log(N))) then increment the result.
|
|
|
|
|
*/
|
|
|
|
|
int shift = 1;
|
|
|
|
|
do {
|
|
|
|
|
alignment |= alignment >> shift;
|
|
|
|
|
shift *= 2;
|
|
|
|
|
} while (unlikely(alignment & (alignment + 1)));
|
|
|
|
|
alignment++;
|
|
|
|
|
}
|
|
|
|
|
return _ha_aligned_alloc(alignment, size);
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-11 12:46:28 -04:00
|
|
|
/* Like above but zeroing the area */
|
|
|
|
|
static inline void *_ha_aligned_zalloc_safe(size_t alignment, size_t size)
|
|
|
|
|
{
|
|
|
|
|
void *ret = _ha_aligned_alloc_safe(alignment, size);
|
|
|
|
|
|
|
|
|
|
if (ret)
|
|
|
|
|
memset(ret, 0, size);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-31 09:26:58 -04:00
|
|
|
/* To be used to free a pointer returned by _ha_aligned_alloc() or
|
|
|
|
|
* _ha_aligned_alloc_safe(). Please use ha_aligned_free() instead
|
|
|
|
|
* (which does perform accounting).
|
|
|
|
|
*/
|
|
|
|
|
static inline void _ha_aligned_free(void *ptr)
|
|
|
|
|
{
|
|
|
|
|
#if defined(_WIN32)
|
|
|
|
|
return _aligned_free(ptr);
|
|
|
|
|
#else
|
|
|
|
|
free(ptr);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-25 09:04:22 -05:00
|
|
|
int parse_dotted_uints(const char *s, unsigned int **nums, size_t *sz);
|
|
|
|
|
|
BUG/MEDIUM: random: implement a thread-safe and process-safe PRNG
This is the replacement of failed attempt to add thread safety and
per-process sequences of random numbers initally tried with commit
1c306aa84d ("BUG/MEDIUM: random: implement per-thread and per-process
random sequences").
This new version takes a completely different approach and doesn't try
to work around the horrible OS-specific and non-portable random API
anymore. Instead it implements "xoroshiro128**", a reputedly high
quality random number generator, which is one of the many variants of
xorshift, which passes all quality tests and which is described here:
http://prng.di.unimi.it/
While not cryptographically secure, it is fast and features a 2^128-1
period. It supports fast jumps allowing to cut the period into smaller
non-overlapping sequences, which we use here to support up to 2^32
processes each having their own, non-overlapping sequence of 2^96
numbers (~7*10^28). This is enough to provide 1 billion randoms per
second and per process for 2200 billion years.
The implementation was made thread-safe either by using a double 64-bit
CAS on platforms supporting it (x86_64, aarch64) or by using a local
lock for the time needed to perform the shift operations. This ensures
that all threads pick numbers from the same pool so that it is not
needed to assign per-thread ranges. For processes we use the fast jump
method to advance the sequence by 2^96 for each process.
Before this patch, the following config:
global
nbproc 8
frontend f
bind :4445
mode http
log stdout format raw daemon
log-format "%[uuid] %pid"
redirect location /
Would produce this output:
a4d0ad64-2645-4b74-b894-48acce0669af 12987
a4d0ad64-2645-4b74-b894-48acce0669af 12992
a4d0ad64-2645-4b74-b894-48acce0669af 12986
a4d0ad64-2645-4b74-b894-48acce0669af 12988
a4d0ad64-2645-4b74-b894-48acce0669af 12991
a4d0ad64-2645-4b74-b894-48acce0669af 12989
a4d0ad64-2645-4b74-b894-48acce0669af 12990
82d5f6cd-f6c1-4f85-a89c-36ae85d26fb9 12987
82d5f6cd-f6c1-4f85-a89c-36ae85d26fb9 12992
82d5f6cd-f6c1-4f85-a89c-36ae85d26fb9 12986
(...)
And now produces:
f94b29b3-da74-4e03-a0c5-a532c635bad9 13011
47470c02-4862-4c33-80e7-a952899570e5 13014
86332123-539a-47bf-853f-8c8ea8b2a2b5 13013
8f9efa99-3143-47b2-83cf-d618c8dea711 13012
3cc0f5c7-d790-496b-8d39-bec77647af5b 13015
3ec64915-8f95-4374-9e66-e777dc8791e0 13009
0f9bf894-dcde-408c-b094-6e0bb3255452 13011
49c7bfde-3ffb-40e9-9a8d-8084d650ed8f 13014
e23f6f2e-35c5-4433-a294-b790ab902653 13012
There are multiple benefits to using this method. First, it doesn't
depend anymore on a non-portable API. Second it's thread safe. Third it
is fast and more proven than any hack we could attempt to try to work
around the deficiencies of the various implementations around.
This commit depends on previous patches "MINOR: tools: add 64-bit rotate
operators" and "BUG/MEDIUM: random: initialize the random pool a bit
better", all of which will need to be backported at least as far as
version 2.0. It doesn't require to backport the build fixes for circular
include files dependecy anymore.
2020-03-07 18:42:37 -05:00
|
|
|
/* PRNG */
|
2024-04-19 15:01:25 -04:00
|
|
|
void ha_generate_uuid_v4(struct buffer *output);
|
2024-04-19 15:01:26 -04:00
|
|
|
void ha_generate_uuid_v7(struct buffer *output);
|
BUG/MEDIUM: random: implement a thread-safe and process-safe PRNG
This is the replacement of failed attempt to add thread safety and
per-process sequences of random numbers initally tried with commit
1c306aa84d ("BUG/MEDIUM: random: implement per-thread and per-process
random sequences").
This new version takes a completely different approach and doesn't try
to work around the horrible OS-specific and non-portable random API
anymore. Instead it implements "xoroshiro128**", a reputedly high
quality random number generator, which is one of the many variants of
xorshift, which passes all quality tests and which is described here:
http://prng.di.unimi.it/
While not cryptographically secure, it is fast and features a 2^128-1
period. It supports fast jumps allowing to cut the period into smaller
non-overlapping sequences, which we use here to support up to 2^32
processes each having their own, non-overlapping sequence of 2^96
numbers (~7*10^28). This is enough to provide 1 billion randoms per
second and per process for 2200 billion years.
The implementation was made thread-safe either by using a double 64-bit
CAS on platforms supporting it (x86_64, aarch64) or by using a local
lock for the time needed to perform the shift operations. This ensures
that all threads pick numbers from the same pool so that it is not
needed to assign per-thread ranges. For processes we use the fast jump
method to advance the sequence by 2^96 for each process.
Before this patch, the following config:
global
nbproc 8
frontend f
bind :4445
mode http
log stdout format raw daemon
log-format "%[uuid] %pid"
redirect location /
Would produce this output:
a4d0ad64-2645-4b74-b894-48acce0669af 12987
a4d0ad64-2645-4b74-b894-48acce0669af 12992
a4d0ad64-2645-4b74-b894-48acce0669af 12986
a4d0ad64-2645-4b74-b894-48acce0669af 12988
a4d0ad64-2645-4b74-b894-48acce0669af 12991
a4d0ad64-2645-4b74-b894-48acce0669af 12989
a4d0ad64-2645-4b74-b894-48acce0669af 12990
82d5f6cd-f6c1-4f85-a89c-36ae85d26fb9 12987
82d5f6cd-f6c1-4f85-a89c-36ae85d26fb9 12992
82d5f6cd-f6c1-4f85-a89c-36ae85d26fb9 12986
(...)
And now produces:
f94b29b3-da74-4e03-a0c5-a532c635bad9 13011
47470c02-4862-4c33-80e7-a952899570e5 13014
86332123-539a-47bf-853f-8c8ea8b2a2b5 13013
8f9efa99-3143-47b2-83cf-d618c8dea711 13012
3cc0f5c7-d790-496b-8d39-bec77647af5b 13015
3ec64915-8f95-4374-9e66-e777dc8791e0 13009
0f9bf894-dcde-408c-b094-6e0bb3255452 13011
49c7bfde-3ffb-40e9-9a8d-8084d650ed8f 13014
e23f6f2e-35c5-4433-a294-b790ab902653 13012
There are multiple benefits to using this method. First, it doesn't
depend anymore on a non-portable API. Second it's thread safe. Third it
is fast and more proven than any hack we could attempt to try to work
around the deficiencies of the various implementations around.
This commit depends on previous patches "MINOR: tools: add 64-bit rotate
operators" and "BUG/MEDIUM: random: initialize the random pool a bit
better", all of which will need to be backported at least as far as
version 2.0. It doesn't require to backport the build fixes for circular
include files dependecy anymore.
2020-03-07 18:42:37 -05:00
|
|
|
void ha_random_seed(const unsigned char *seed, size_t len);
|
|
|
|
|
void ha_random_jump96(uint32_t dist);
|
CLEANUP: tree-wide: fix prototypes for functions taking no arguments.
"f(void)" is the correct and preferred form for a function taking no
argument, while some places use the older "f()". These were reported
by clang's -Wmissing-prototypes, for example:
src/cpuset.c:111:5: warning: no previous prototype for function 'ha_cpuset_size' [-Wmissing-prototypes]
int ha_cpuset_size()
include/haproxy/cpuset.h:42:5: note: this declaration is not a prototype; add 'void' to make it a prototype for a zero-parameter function
int ha_cpuset_size();
^
void
This aggregate patch fixes this for the following functions:
ha_backtrace_to_stderr(), ha_cpuset_size(), ha_panic(), ha_random64(),
ha_thread_dump_all_to_trash(), get_exec_path(), check_config_validity(),
mworker_child_nb(), mworker_cli_proxy_(create|stop)(),
mworker_cleantasks(), mworker_cleanlisteners(), mworker_ext_launch_all(),
mworker_reload(), mworker_(env|proc_list)_to_(proc_list|env)(),
mworker_(un|)block_signals(), proxy_adjust_all_maxconn(),
proxy_destroy_all_defaults(), get_tainted(),
pool_total_(allocated|used)(), thread_isolate(_full|)(),
thread(_sync|)_release(), thread_harmless_till_end(),
thread_cpu_mask_forced(), dequeue_all_listeners(), next_timer_expiry(),
wake_expired_tasks(), process_runnable_tasks(), init_acl(),
init_buffer(), (de|)init_log_buffers(), (de|)init_pollers(),
fork_poller(), pool_destroy_all(), pool_evict_from_local_caches(),
pool_total_failures(), dump_pools_to_trash(), cfg_run_diagnostics(),
tv_init_(process|thread)_date(), __signal_process_queue(),
deinit_signals(), haproxy_unblock_signals()
2021-09-12 06:49:33 -04:00
|
|
|
uint64_t ha_random64(void);
|
BUG/MEDIUM: random: implement a thread-safe and process-safe PRNG
This is the replacement of failed attempt to add thread safety and
per-process sequences of random numbers initally tried with commit
1c306aa84d ("BUG/MEDIUM: random: implement per-thread and per-process
random sequences").
This new version takes a completely different approach and doesn't try
to work around the horrible OS-specific and non-portable random API
anymore. Instead it implements "xoroshiro128**", a reputedly high
quality random number generator, which is one of the many variants of
xorshift, which passes all quality tests and which is described here:
http://prng.di.unimi.it/
While not cryptographically secure, it is fast and features a 2^128-1
period. It supports fast jumps allowing to cut the period into smaller
non-overlapping sequences, which we use here to support up to 2^32
processes each having their own, non-overlapping sequence of 2^96
numbers (~7*10^28). This is enough to provide 1 billion randoms per
second and per process for 2200 billion years.
The implementation was made thread-safe either by using a double 64-bit
CAS on platforms supporting it (x86_64, aarch64) or by using a local
lock for the time needed to perform the shift operations. This ensures
that all threads pick numbers from the same pool so that it is not
needed to assign per-thread ranges. For processes we use the fast jump
method to advance the sequence by 2^96 for each process.
Before this patch, the following config:
global
nbproc 8
frontend f
bind :4445
mode http
log stdout format raw daemon
log-format "%[uuid] %pid"
redirect location /
Would produce this output:
a4d0ad64-2645-4b74-b894-48acce0669af 12987
a4d0ad64-2645-4b74-b894-48acce0669af 12992
a4d0ad64-2645-4b74-b894-48acce0669af 12986
a4d0ad64-2645-4b74-b894-48acce0669af 12988
a4d0ad64-2645-4b74-b894-48acce0669af 12991
a4d0ad64-2645-4b74-b894-48acce0669af 12989
a4d0ad64-2645-4b74-b894-48acce0669af 12990
82d5f6cd-f6c1-4f85-a89c-36ae85d26fb9 12987
82d5f6cd-f6c1-4f85-a89c-36ae85d26fb9 12992
82d5f6cd-f6c1-4f85-a89c-36ae85d26fb9 12986
(...)
And now produces:
f94b29b3-da74-4e03-a0c5-a532c635bad9 13011
47470c02-4862-4c33-80e7-a952899570e5 13014
86332123-539a-47bf-853f-8c8ea8b2a2b5 13013
8f9efa99-3143-47b2-83cf-d618c8dea711 13012
3cc0f5c7-d790-496b-8d39-bec77647af5b 13015
3ec64915-8f95-4374-9e66-e777dc8791e0 13009
0f9bf894-dcde-408c-b094-6e0bb3255452 13011
49c7bfde-3ffb-40e9-9a8d-8084d650ed8f 13014
e23f6f2e-35c5-4433-a294-b790ab902653 13012
There are multiple benefits to using this method. First, it doesn't
depend anymore on a non-portable API. Second it's thread safe. Third it
is fast and more proven than any hack we could attempt to try to work
around the deficiencies of the various implementations around.
This commit depends on previous patches "MINOR: tools: add 64-bit rotate
operators" and "BUG/MEDIUM: random: initialize the random pool a bit
better", all of which will need to be backported at least as far as
version 2.0. It doesn't require to backport the build fixes for circular
include files dependecy anymore.
2020-03-07 18:42:37 -05:00
|
|
|
|
|
|
|
|
static inline uint32_t ha_random32()
|
|
|
|
|
{
|
|
|
|
|
return ha_random64() >> 32;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline int32_t ha_random()
|
|
|
|
|
{
|
|
|
|
|
return ha_random32() >> 1;
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-02 08:01:35 -05:00
|
|
|
extern THREAD_LOCAL unsigned int statistical_prng_state;
|
|
|
|
|
|
|
|
|
|
/* Xorshift RNGs from http://www.jstatsoft.org/v08/i14/paper.
|
|
|
|
|
* This has a (2^32)-1 period, only zero is never returned.
|
|
|
|
|
*/
|
|
|
|
|
static inline unsigned int statistical_prng()
|
|
|
|
|
{
|
|
|
|
|
unsigned int x = statistical_prng_state;
|
|
|
|
|
|
|
|
|
|
x ^= x << 13;
|
|
|
|
|
x ^= x >> 17;
|
|
|
|
|
x ^= x << 5;
|
|
|
|
|
return statistical_prng_state = x;
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-17 09:49:34 -04:00
|
|
|
/* returns a random number between 0 and <range> - 1 that is evenly distributed
|
|
|
|
|
* over the range.
|
|
|
|
|
*/
|
|
|
|
|
static inline uint statistical_prng_range(uint range)
|
|
|
|
|
{
|
2022-07-18 13:09:55 -04:00
|
|
|
return mul32hi(statistical_prng(), range ? range - 1 : 0);
|
2021-04-17 09:49:34 -04:00
|
|
|
}
|
|
|
|
|
|
2022-09-07 04:56:03 -04:00
|
|
|
/* returns a hash on <bits> bits of pointer <p> that is suitable for being used
|
|
|
|
|
* to compute statistic buckets, in that it's fast and reasonably distributed
|
|
|
|
|
* thanks to mixing the bits via a multiplication by a prime number and using
|
|
|
|
|
* the middle bits on 64-bit platforms or remixing the topmost with lowest ones
|
OPTIM: tools: improve hash distribution using a better prime seed
During tests it was noticed that the current hash is not that good
on 4- and 5- bit hashes. About 7.5% of all the 32-bit primes were tested
as candidates for the hash function, by submitting them 128 arrangements
of N pointers among 40k extracted from haproxy's pools, and the average
fill rates for 1- to 12- bit hashes were measured and compared. It was
clear that some values do not provide great hashes and other ones are
way more resistant.
The current value is not bad at all but delivers 42.6% unique 2-bit
outputs, 41.6% 3-bit, 38.0% 4-bit, 38.2% 5-bit and 37.1% 10-bit. Some
values did perform significantly better, among which 0xacd1be85 which
does 43.2% 2-bit, 42.5% 3-bit, 42.2% 4-bit, 39.2% 5-bit and 37.3% 10-bit.
The reverse value used in the ptr2_hash() was really underperforming and
was replaced with 0x9d28e4e9 which does 49.6%, 40.4%, 42.6%, 39.1%, and
37.2% respectvely.
This should slightly improve the accuracy of the task and memory
profiling, and will be useful for pools.
2023-08-12 11:28:13 -04:00
|
|
|
* on 32-bit. The distribution is smooth enough for the hash to provide on
|
|
|
|
|
* average 1/e non-colliding entries per input, and use on average 1-1/e
|
|
|
|
|
* entries total. Thus for example hashing 1024 random valid pointers will
|
|
|
|
|
* result on average in ~647 distinct keys, 377 of which are unique. It was
|
|
|
|
|
* carefully selected to deliver optimal distribution for low bit counts so
|
|
|
|
|
* that hashing on 2,3,4 or 5 bits delivers good results.
|
2022-09-07 04:56:03 -04:00
|
|
|
*/
|
|
|
|
|
static forceinline uint ptr_hash(const void *p, const int bits)
|
|
|
|
|
{
|
|
|
|
|
unsigned long long x = (unsigned long)p;
|
|
|
|
|
|
2023-07-25 10:59:48 -04:00
|
|
|
if (!bits)
|
|
|
|
|
return 0;
|
|
|
|
|
|
OPTIM: tools: improve hash distribution using a better prime seed
During tests it was noticed that the current hash is not that good
on 4- and 5- bit hashes. About 7.5% of all the 32-bit primes were tested
as candidates for the hash function, by submitting them 128 arrangements
of N pointers among 40k extracted from haproxy's pools, and the average
fill rates for 1- to 12- bit hashes were measured and compared. It was
clear that some values do not provide great hashes and other ones are
way more resistant.
The current value is not bad at all but delivers 42.6% unique 2-bit
outputs, 41.6% 3-bit, 38.0% 4-bit, 38.2% 5-bit and 37.1% 10-bit. Some
values did perform significantly better, among which 0xacd1be85 which
does 43.2% 2-bit, 42.5% 3-bit, 42.2% 4-bit, 39.2% 5-bit and 37.3% 10-bit.
The reverse value used in the ptr2_hash() was really underperforming and
was replaced with 0x9d28e4e9 which does 49.6%, 40.4%, 42.6%, 39.1%, and
37.2% respectvely.
This should slightly improve the accuracy of the task and memory
profiling, and will be useful for pools.
2023-08-12 11:28:13 -04:00
|
|
|
x *= 0xacd1be85U;
|
2022-09-07 04:56:03 -04:00
|
|
|
if (sizeof(long) == 4)
|
|
|
|
|
x ^= x >> 32;
|
|
|
|
|
else
|
2023-08-11 14:11:30 -04:00
|
|
|
x >>= 31 - (bits + 1) / 2;
|
2022-09-07 04:56:03 -04:00
|
|
|
return x & (~0U >> (-bits & 31));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Same as above but works on two pointers. It will return the same values
|
|
|
|
|
* if the second pointer is NULL.
|
|
|
|
|
*/
|
|
|
|
|
static forceinline uint ptr2_hash(const void *p1, const void *p2, const int bits)
|
|
|
|
|
{
|
|
|
|
|
unsigned long long x = (unsigned long)p1;
|
|
|
|
|
unsigned long long y = (unsigned long)p2;
|
|
|
|
|
|
2023-07-25 10:59:48 -04:00
|
|
|
if (!bits)
|
|
|
|
|
return 0;
|
|
|
|
|
|
OPTIM: tools: improve hash distribution using a better prime seed
During tests it was noticed that the current hash is not that good
on 4- and 5- bit hashes. About 7.5% of all the 32-bit primes were tested
as candidates for the hash function, by submitting them 128 arrangements
of N pointers among 40k extracted from haproxy's pools, and the average
fill rates for 1- to 12- bit hashes were measured and compared. It was
clear that some values do not provide great hashes and other ones are
way more resistant.
The current value is not bad at all but delivers 42.6% unique 2-bit
outputs, 41.6% 3-bit, 38.0% 4-bit, 38.2% 5-bit and 37.1% 10-bit. Some
values did perform significantly better, among which 0xacd1be85 which
does 43.2% 2-bit, 42.5% 3-bit, 42.2% 4-bit, 39.2% 5-bit and 37.3% 10-bit.
The reverse value used in the ptr2_hash() was really underperforming and
was replaced with 0x9d28e4e9 which does 49.6%, 40.4%, 42.6%, 39.1%, and
37.2% respectvely.
This should slightly improve the accuracy of the task and memory
profiling, and will be useful for pools.
2023-08-12 11:28:13 -04:00
|
|
|
x *= 0xacd1be85U;
|
|
|
|
|
y *= 0x9d28e4e9U;
|
2022-09-07 04:56:03 -04:00
|
|
|
x ^= y;
|
|
|
|
|
if (sizeof(long) == 4)
|
|
|
|
|
x ^= x >> 32;
|
|
|
|
|
else
|
|
|
|
|
x >>= 33 - bits / 2;
|
|
|
|
|
return x & (~0U >> (-bits & 31));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-03-12 12:59:31 -05:00
|
|
|
/* Update array <fp> with the character transition <prev> to <curr>. If <prev>
|
|
|
|
|
* is zero, it's assumed that <curr> is the first character. If <curr> is zero
|
|
|
|
|
* its assumed to mark the end. Both may be zero. <fp> is a 1024-entries array
|
|
|
|
|
* indexed as 32*from+to. Positions for 'from' and 'to' are:
|
2021-03-15 04:34:27 -04:00
|
|
|
* 1..26=letter, 27=digit, 28=other/begin/end.
|
|
|
|
|
* Row "from=0" is used to mark the character's presence. Others unused.
|
2021-03-12 12:59:31 -05:00
|
|
|
*/
|
|
|
|
|
static inline void update_char_fingerprint(uint8_t *fp, char prev, char curr)
|
|
|
|
|
{
|
|
|
|
|
int from, to;
|
|
|
|
|
|
|
|
|
|
switch (prev) {
|
2021-03-15 04:34:27 -04:00
|
|
|
case 0: from = 28; break; // begin
|
|
|
|
|
case 'a'...'z': from = prev - 'a' + 1; break;
|
2024-07-18 07:20:04 -04:00
|
|
|
case 'A'...'Z': from = tolower((unsigned char)prev) - 'a' + 1; break;
|
2021-03-15 04:34:27 -04:00
|
|
|
case '0'...'9': from = 27; break;
|
|
|
|
|
default: from = 28; break;
|
2021-03-12 12:59:31 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (curr) {
|
|
|
|
|
case 0: to = 28; break; // end
|
2021-03-15 04:34:27 -04:00
|
|
|
case 'a'...'z': to = curr - 'a' + 1; break;
|
2024-07-18 07:20:04 -04:00
|
|
|
case 'A'...'Z': to = tolower((unsigned char)curr) - 'a' + 1; break;
|
2021-03-15 04:34:27 -04:00
|
|
|
case '0'...'9': to = 27; break;
|
|
|
|
|
default: to = 28; break;
|
2021-03-12 12:59:31 -05:00
|
|
|
}
|
2021-03-15 04:34:27 -04:00
|
|
|
if (curr)
|
|
|
|
|
fp[to] = 1;
|
2021-03-12 12:59:31 -05:00
|
|
|
fp[32 * from + to]++;
|
|
|
|
|
}
|
2021-03-02 08:01:35 -05:00
|
|
|
|
2024-11-18 13:47:59 -05:00
|
|
|
/* checks that the numerical argument, if passed without units and is non-zero,
|
|
|
|
|
* is at least as large as value <min>. It returns 1 if the value is too small,
|
|
|
|
|
* otherwise zero. This is used to warn about the use of small values without
|
|
|
|
|
* units.
|
|
|
|
|
*/
|
|
|
|
|
static inline int warn_if_lower(const char *text, long min)
|
|
|
|
|
{
|
|
|
|
|
int digits;
|
|
|
|
|
long value;
|
|
|
|
|
|
|
|
|
|
digits = strspn(text, "0123456789");
|
|
|
|
|
if (digits < strlen(text))
|
|
|
|
|
return 0; // there are non-digits here.
|
|
|
|
|
|
|
|
|
|
value = atol(text);
|
|
|
|
|
return value && value < min;
|
|
|
|
|
}
|
2025-11-14 04:23:45 -05:00
|
|
|
/* compare the current AWS-LC API number to a string */
|
|
|
|
|
int awslc_compare_current_api(const char *version);
|
2021-08-21 17:59:56 -04:00
|
|
|
/* compare the current OpenSSL version to a string */
|
|
|
|
|
int openssl_compare_current_version(const char *version);
|
2021-10-11 09:34:12 -04:00
|
|
|
/* compare the current OpenSSL name to a string */
|
|
|
|
|
int openssl_compare_current_name(const char *name);
|
2021-08-21 17:59:56 -04:00
|
|
|
|
2024-05-16 06:08:56 -04:00
|
|
|
/* vma helpers */
|
|
|
|
|
void vma_set_name(void *addr, size_t size, const char *type, const char *name);
|
2024-05-24 04:29:08 -04:00
|
|
|
void vma_set_name_id(void *addr, size_t size, const char *type, const char *name, unsigned int id);
|
2024-05-16 06:08:56 -04:00
|
|
|
|
2024-08-05 04:03:46 -04:00
|
|
|
/* cfgparse helpers */
|
|
|
|
|
char *fgets_from_mem(char* buf, int size, const char **position, const char *end);
|
|
|
|
|
|
MINOR: tools: add helpers to backup/clean/restore env
'setenv', 'presetenv', 'unsetenv', 'resetenv' keywords in configuration could
modify the process runtime environment. In case of master-worker mode this
creates a problem, as the configuration is read only once before the forking a
worker and then the master process does the reexec without reading any config
files, just to free the memory. So, during the reload a new worker process will
be created, but it will inherited the previous unchanged environment from the
master in wait mode, thus it won't benefit the changes in configuration,
related to '*env' keywords. This may cause unexpected behavior or some parser
errors in master-worker mode.
So, let's add a helper to backup all process env variables just before it will
read its configuration. And let's also add helpers to clean up the current
runtime environment and to restore it to its initial state (as it was before
parsing the config).
2024-08-21 13:06:33 -04:00
|
|
|
/* helpers to backup/clean/restore process env */
|
|
|
|
|
int backup_env(void);
|
|
|
|
|
int clean_env(void);
|
|
|
|
|
int restore_env(void);
|
|
|
|
|
|
2024-09-20 17:14:41 -04:00
|
|
|
/* helper to print the name of errno's corresponding macro (for example "EINVAL"
|
|
|
|
|
* for errno=22) instead of calling strerror(errno).
|
|
|
|
|
*/
|
|
|
|
|
#define CASE_ERR(err) \
|
|
|
|
|
case err: return #err
|
|
|
|
|
|
|
|
|
|
static inline const char *errname(int err_num, char **out)
|
|
|
|
|
{
|
|
|
|
|
/* only currently used errno values, please, add a new one, if you
|
|
|
|
|
* start using it in the code.
|
|
|
|
|
*/
|
|
|
|
|
switch (err_num) {
|
|
|
|
|
case 0: return "SUCCESS";
|
|
|
|
|
CASE_ERR(EPERM);
|
|
|
|
|
CASE_ERR(ENOENT);
|
|
|
|
|
CASE_ERR(EINTR);
|
|
|
|
|
CASE_ERR(EIO);
|
|
|
|
|
CASE_ERR(E2BIG);
|
|
|
|
|
CASE_ERR(EBADF);
|
|
|
|
|
CASE_ERR(ECHILD);
|
|
|
|
|
CASE_ERR(EAGAIN);
|
|
|
|
|
CASE_ERR(ENOMEM);
|
|
|
|
|
CASE_ERR(EACCES);
|
|
|
|
|
CASE_ERR(EFAULT);
|
|
|
|
|
CASE_ERR(EINVAL);
|
|
|
|
|
CASE_ERR(ENFILE);
|
|
|
|
|
CASE_ERR(EMFILE);
|
|
|
|
|
CASE_ERR(ENOSPC);
|
|
|
|
|
CASE_ERR(ERANGE);
|
|
|
|
|
CASE_ERR(ENOSYS);
|
|
|
|
|
CASE_ERR(EADDRINUSE);
|
|
|
|
|
CASE_ERR(ECONNABORTED);
|
|
|
|
|
CASE_ERR(ECONNRESET);
|
|
|
|
|
CASE_ERR(EINPROGRESS);
|
|
|
|
|
CASE_ERR(ENOTCONN);
|
|
|
|
|
CASE_ERR(EADDRNOTAVAIL);
|
|
|
|
|
CASE_ERR(ECONNREFUSED);
|
|
|
|
|
CASE_ERR(ENETUNREACH);
|
|
|
|
|
CASE_ERR(EPROTO);
|
|
|
|
|
CASE_ERR(ENOTSOCK);
|
|
|
|
|
CASE_ERR(EMSGSIZE);
|
|
|
|
|
CASE_ERR(EPROTONOSUPPORT);
|
|
|
|
|
CASE_ERR(EAFNOSUPPORT);
|
|
|
|
|
CASE_ERR(ENOBUFS);
|
|
|
|
|
CASE_ERR(EISCONN);
|
|
|
|
|
CASE_ERR(ETIMEDOUT);
|
|
|
|
|
CASE_ERR(EALREADY);
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
memprintf(out, "%d", err_num);
|
|
|
|
|
return *out;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-19 11:16:52 -04:00
|
|
|
int path_base(const char *path, const char *base, char *dst, char **err);
|
|
|
|
|
|
2025-05-09 13:09:12 -04:00
|
|
|
void ha_freearray(char ***array);
|
|
|
|
|
|
2020-06-03 12:09:46 -04:00
|
|
|
#endif /* _HAPROXY_TOOLS_H */
|