mirror of
https://github.com/haproxy/haproxy.git
synced 2026-05-25 18:52:21 -04:00
Compare commits
No commits in common. "master" and "v3.4-dev13" have entirely different histories.
master
...
v3.4-dev13
33 changed files with 107 additions and 221 deletions
|
|
@ -3329,7 +3329,7 @@ setenv <name> <value>
|
|||
the configuration file sees the new value. See also "presetenv", "resetenv",
|
||||
and "unsetenv".
|
||||
|
||||
shm-stats-file <name>
|
||||
shm-stats-file <name> [ EXPERIMENTAL ]
|
||||
When this directive is set, it enables the use of shared memory for storing
|
||||
stats counters. <name> is used as argument to shm_open() to open the shared
|
||||
memory at a unique location. It also means that the directive is only
|
||||
|
|
@ -3345,7 +3345,7 @@ shm-stats-file <name>
|
|||
|
||||
See also "guid", "guid-prefix" and "shm-stats-file-max-objects"
|
||||
|
||||
shm-stats-file-max-objects <number>
|
||||
shm-stats-file-max-objects <number> [ EXPERIMENTAL ]
|
||||
This setting defines the maximum number of objects the shared memory used
|
||||
for shared counters will be able to store per thread group. It is directly
|
||||
related to the maximum memory size of the shm and is used to "premap" the
|
||||
|
|
|
|||
|
|
@ -179,8 +179,6 @@ enum {
|
|||
/* below we have all handshake flags grouped into one */
|
||||
CO_FL_HANDSHAKE = CO_FL_SEND_PROXY | CO_FL_ACCEPT_PROXY | CO_FL_ACCEPT_CIP | CO_FL_SOCKS4_SEND | CO_FL_SOCKS4_RECV,
|
||||
CO_FL_WAIT_XPRT = CO_FL_WAIT_L4_CONN | CO_FL_HANDSHAKE | CO_FL_WAIT_L6_CONN,
|
||||
/* handshake running on top of a layer6 */
|
||||
CO_FL_WAIT_XPRT_L6 = CO_FL_QMUX_SEND | CO_FL_QMUX_RECV,
|
||||
|
||||
CO_FL_SSL_WAIT_HS = 0x08000000, /* wait for an SSL handshake to complete */
|
||||
|
||||
|
|
|
|||
|
|
@ -114,7 +114,6 @@ int conn_reverse(struct connection *conn);
|
|||
const char *conn_err_code_name(struct connection *c);
|
||||
const char *conn_err_code_str(struct connection *c);
|
||||
int xprt_add_hs(struct connection *conn);
|
||||
int xprt_add_l6hs(struct connection *conn, int xprt);
|
||||
void register_mux_proto(struct mux_proto_list *list);
|
||||
|
||||
static inline void conn_report_term_evt(struct connection *conn, enum term_event_loc loc, unsigned char type);
|
||||
|
|
|
|||
|
|
@ -121,8 +121,8 @@ static inline size_t array_size_or_fail(size_t m, size_t n)
|
|||
{
|
||||
size_t size;
|
||||
|
||||
if (unlikely(mulsz_overflow(m, n, &size)))
|
||||
return DISGUISE(~(size_t)0);
|
||||
if (mulsz_overflow(m, n, &size))
|
||||
return ~(size_t)0;
|
||||
return size;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* include/haproxy/resolvers-t.h
|
||||
* include/haproxy/dns-t.h
|
||||
* This file provides structures and types for DNS.
|
||||
*
|
||||
* Copyright (C) 2014 Baptiste Assmann <bedis9@gmail.com>
|
||||
|
|
@ -114,7 +114,7 @@ struct resolv_answer_item {
|
|||
char name[DNS_MAX_NAME_SIZE+1]; /* answer name */
|
||||
int16_t type; /* question type */
|
||||
int16_t class; /* query class */
|
||||
uint32_t ttl; /* response TTL */
|
||||
int32_t ttl; /* response TTL */
|
||||
int16_t priority; /* SRV type priority */
|
||||
uint16_t weight; /* SRV type weight */
|
||||
uint16_t port; /* SRV type port */
|
||||
|
|
@ -281,7 +281,7 @@ enum {
|
|||
* matching preference was found.
|
||||
*/
|
||||
RSLV_UPD_SRVIP_NOT_FOUND, /* provided IP not found
|
||||
* OR provided IP found and preference is not matched and an IP
|
||||
* OR provided IP found and preference is not match and an IP
|
||||
* matching preference was found.
|
||||
*/
|
||||
RSLV_UPD_NO_IP_FOUND, /* no IP could be found in the response */
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* include/haproxy/resolvers.h
|
||||
* include/haproxy/dns.h
|
||||
* This file provides functions related to DNS protocol
|
||||
*
|
||||
* Copyright (C) 2014 Baptiste Assmann <bedis9@gmail.com>
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ struct certificate_ocsp {
|
|||
int refcount_store; /* Number of ckch_store that reference this certificate_ocsp */
|
||||
int refcount; /* Number of actual references to this certificate_ocsp (SSL_CTXs mostly) */
|
||||
struct buffer response;
|
||||
unsigned long expire;
|
||||
long expire;
|
||||
X509 *issuer;
|
||||
STACK_OF(X509) *chain;
|
||||
struct eb64_node next_update; /* Key of items inserted in ocsp_update_tree (sorted by absolute date) */
|
||||
|
|
|
|||
10
src/acme.c
10
src/acme.c
|
|
@ -1562,16 +1562,6 @@ int acme_res_certificate(struct task *task, struct acme_ctx *ctx, char **errmsg)
|
|||
key = ctx->store->data->key;
|
||||
ctx->store->data->key = NULL;
|
||||
|
||||
/* OpenSSL's BIO_new_mem_buf() expects a NUL-terminated string when
|
||||
* passed -1. The httpclient buffer lacks this, so manually terminate
|
||||
* it here to prevent an out-of-bounds heap read during PEM parsing.
|
||||
*/
|
||||
if (b_room(&hc->res.buf) < 1) {
|
||||
memprintf(errmsg, "ACME certificate response has no room for NUL terminator");
|
||||
goto error;
|
||||
}
|
||||
hc->res.buf.area[hc->res.buf.data] = '\0';
|
||||
|
||||
/* XXX: might need a function dedicated to this, which does not read a private key */
|
||||
if (ssl_sock_load_pem_into_ckch(ctx->store->path, hc->res.buf.area, ctx->store->data , errmsg) != 0)
|
||||
goto error;
|
||||
|
|
|
|||
|
|
@ -539,6 +539,9 @@ size_t appctx_rcv_buf(struct stconn *sc, struct buffer *buf, size_t count, unsig
|
|||
if (applet_fl_test(appctx, APPCTX_FL_OUTBLK_ALLOC))
|
||||
goto end;
|
||||
|
||||
if (!count)
|
||||
goto end;
|
||||
|
||||
if (!appctx_get_buf(appctx, &appctx->outbuf)) {
|
||||
TRACE_STATE("waiting for appctx outbuf allocation", APPLET_EV_RECV|APPLET_EV_BLK, appctx);
|
||||
goto end;
|
||||
|
|
@ -547,8 +550,7 @@ size_t appctx_rcv_buf(struct stconn *sc, struct buffer *buf, size_t count, unsig
|
|||
if (flags & CO_RFL_BUF_FLUSH)
|
||||
applet_fl_set(appctx, APPCTX_FL_FASTFWD);
|
||||
|
||||
if (count)
|
||||
ret = CALL_APPLET_WITH_RET(appctx->applet, rcv_buf(appctx, buf, count, flags));
|
||||
ret = CALL_APPLET_WITH_RET(appctx->applet, rcv_buf(appctx, buf, count, flags));
|
||||
if (ret)
|
||||
applet_fl_clr(appctx, APPCTX_FL_OUTBLK_FULL);
|
||||
|
||||
|
|
|
|||
|
|
@ -1818,7 +1818,7 @@ int connect_server(struct stream *s)
|
|||
{
|
||||
struct connection *cli_conn = objt_conn(strm_orig(s));
|
||||
struct connection *srv_conn = NULL;
|
||||
const struct mux_proto_list *mux_proto = NULL;
|
||||
const struct mux_proto_list *mux_proto;
|
||||
struct server *srv;
|
||||
struct ist name = IST_NULL;
|
||||
struct sample *name_smp;
|
||||
|
|
@ -2139,10 +2139,12 @@ int connect_server(struct stream *s)
|
|||
}
|
||||
|
||||
if (may_start_mux_now) {
|
||||
/* Delay MUX init if an XPRT handshake is required prior. */
|
||||
/* Delay QMux MUX init to let xprt_qmux handshake runs first. */
|
||||
mux_proto = conn_select_mux_be(srv_conn);
|
||||
if (mux_proto && mux_proto->init_xprt)
|
||||
if (mux_proto && mux_proto->init_xprt == XPRT_QMUX) {
|
||||
srv_conn->flags |= (CO_FL_QMUX_RECV|CO_FL_QMUX_SEND);
|
||||
may_start_mux_now = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(USE_OPENSSL) && defined(TLSEXT_TYPE_application_layer_protocol_negotiation)
|
||||
|
|
@ -2252,13 +2254,6 @@ int connect_server(struct stream *s)
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (mux_proto && mux_proto->init_xprt) {
|
||||
/* Add handshake layer prior to MUX init if required. Does nothing if SSL layer is active though. */
|
||||
if (xprt_add_l6hs(srv_conn, mux_proto->init_xprt)) {
|
||||
conn_full_close(srv_conn);
|
||||
return SF_ERR_INTERNAL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Now that the mux may have been created, we can start the xprt.
|
||||
|
|
|
|||
12
src/cache.c
12
src/cache.c
|
|
@ -2180,17 +2180,7 @@ enum act_return http_action_req_cache_use(struct act_rule *rule, struct proxy *p
|
|||
sec_entry = get_secondary_entry(cache_tree, res,
|
||||
s->txn.http->cache_secondary_hash,
|
||||
0);
|
||||
if (!sec_entry) {
|
||||
/* Secondary key miss: release the retained primary entry
|
||||
* and reattach the detached row before returning.
|
||||
*/
|
||||
release_entry(cache_tree, res, 0);
|
||||
shctx_wrlock(shctx);
|
||||
if (detached)
|
||||
shctx_row_reattach(shctx, entry_block);
|
||||
shctx_wrunlock(shctx);
|
||||
}
|
||||
else if (sec_entry != res) {
|
||||
if (sec_entry && sec_entry != res) {
|
||||
/* The wrong row was added to the hot list. */
|
||||
release_entry(cache_tree, res, 0);
|
||||
retain_entry(sec_entry);
|
||||
|
|
|
|||
|
|
@ -1629,6 +1629,11 @@ static int cfg_parse_global_shm_stats_file(char **args, int section_type,
|
|||
struct proxy *curpx, const struct proxy *defpx,
|
||||
const char *file, int line, char **err)
|
||||
{
|
||||
if (!experimental_directives_allowed) {
|
||||
memprintf(err, "'%s' directive is experimental, must be allowed via a global 'expose-experimental-directives'", args[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (global.shm_stats_file != NULL) {
|
||||
memprintf(err, "'%s' already specified.\n", args[0]);
|
||||
return -1;
|
||||
|
|
@ -1639,6 +1644,7 @@ static int cfg_parse_global_shm_stats_file(char **args, int section_type,
|
|||
return -1;
|
||||
}
|
||||
|
||||
mark_tainted(TAINTED_CONFIG_EXP_KW_DECLARED);
|
||||
global.shm_stats_file = strdup(args[1]);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1647,6 +1653,11 @@ static int cfg_parse_global_shm_stats_file_max_objects(char **args, int section_
|
|||
struct proxy *curpx, const struct proxy *defpx,
|
||||
const char *file, int line, char **err)
|
||||
{
|
||||
if (!experimental_directives_allowed) {
|
||||
memprintf(err, "'%s' directive is experimental, must be allowed via a global 'expose-experimental-directives'", args[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (shm_stats_file_max_objects != -1) {
|
||||
memprintf(err, "'%s' already specified.\n", args[0]);
|
||||
return -1;
|
||||
|
|
@ -1657,6 +1668,7 @@ static int cfg_parse_global_shm_stats_file_max_objects(char **args, int section_
|
|||
return -1;
|
||||
}
|
||||
|
||||
mark_tainted(TAINTED_CONFIG_EXP_KW_DECLARED);
|
||||
shm_stats_file_max_objects = atoi(args[1]);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1151,13 +1151,8 @@ int cli_parse_cmdline(struct appctx *appctx)
|
|||
*/
|
||||
if (len-1 == strlen(appctx->cli_ctx.payload_pat)) {
|
||||
if (strncmp(str, appctx->cli_ctx.payload_pat, len-1) == 0) {
|
||||
/* end of payload was reached, rewind before the previous \n, if any, and replace it by a \0
|
||||
* Otherwise, the payload is empty, just
|
||||
*/
|
||||
if (b_data(buf) > len)
|
||||
b_sub(buf, len+1);
|
||||
else
|
||||
b_sub(buf, len);
|
||||
/* end of payload was reached, rewind before the previous \n and replace it by a \0 */
|
||||
b_sub(buf, strlen(appctx->cli_ctx.payload_pat) + 2);
|
||||
*b_tail(buf) = '\0';
|
||||
appctx->st1 &= ~APPCTX_CLI_ST1_PAYLOAD;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -196,7 +196,7 @@ int conn_notify_mux(struct connection *conn, int old_flags, int forced_wake)
|
|||
* information to create one, typically from the ALPN. If we're
|
||||
* done with the handshake, attempt to create one.
|
||||
*/
|
||||
if (unlikely(!conn->mux) && !(conn->flags & (CO_FL_WAIT_XPRT|CO_FL_WAIT_XPRT_L6))) {
|
||||
if (unlikely(!conn->mux) && !(conn->flags & (CO_FL_WAIT_XPRT|CO_FL_QMUX_RECV|CO_FL_QMUX_SEND))) {
|
||||
ret = conn_create_mux(conn, NULL);
|
||||
if (ret < 0)
|
||||
goto done;
|
||||
|
|
@ -847,43 +847,6 @@ int xprt_add_hs(struct connection *conn)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Activates an <xprt> layer on top of <conn> connection. This handshake layer
|
||||
* should be designed to work on top of the layer 6. If SSL is active and its
|
||||
* handshake still in progress, this function does nothing.
|
||||
*
|
||||
* Returns 0 on success else a negative error code.
|
||||
*/
|
||||
int xprt_add_l6hs(struct connection *conn, int xprt)
|
||||
{
|
||||
const struct xprt_ops *ops = xprt_get(xprt);
|
||||
void *ops_ctx = NULL;
|
||||
|
||||
/* Only QMux is supported as handshake on top of layer6 for now. */
|
||||
BUG_ON(xprt != XPRT_QMUX);
|
||||
|
||||
if (conn->flags & CO_FL_ERROR)
|
||||
return -1;
|
||||
|
||||
/* Do nothing if SSL is in used but handshake still in progress. In
|
||||
* this case, xprt layer will be added on handshake completion.
|
||||
*/
|
||||
if (conn->xprt == xprt_get(XPRT_SSL) &&
|
||||
(conn->flags & CO_FL_WAIT_L6_CONN)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ops->init(conn, &ops_ctx))
|
||||
return -1;
|
||||
|
||||
ops->add_xprt(conn, ops_ctx, conn->xprt_ctx, conn->xprt, NULL, NULL);
|
||||
conn->xprt = ops;
|
||||
conn->xprt_ctx = ops_ctx;
|
||||
/* Reset XPRT READY flag before the next conn_xprt_start(). */
|
||||
conn->flags &= ~CO_FL_XPRT_READY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* returns a short name for an error, typically the same as the enum name
|
||||
* without the "CO_ER_" prefix, or an empty string for no error (better eye
|
||||
* catching in logs). This is more compact for some debug cases.
|
||||
|
|
|
|||
24
src/dict.c
24
src/dict.c
|
|
@ -79,7 +79,7 @@ static struct dict_entry *__dict_lookup(struct dict *d, const char *s)
|
|||
*/
|
||||
struct dict_entry *dict_insert(struct dict *d, char *s)
|
||||
{
|
||||
struct dict_entry *de, *tree_de;
|
||||
struct dict_entry *de;
|
||||
struct ebpt_node *n;
|
||||
|
||||
HA_RWLOCK_RDLOCK(DICT_LOCK, &d->rwlock);
|
||||
|
|
@ -97,18 +97,13 @@ struct dict_entry *dict_insert(struct dict *d, char *s)
|
|||
|
||||
HA_RWLOCK_WRLOCK(DICT_LOCK, &d->rwlock);
|
||||
n = ebis_insert(&d->values, &de->value);
|
||||
tree_de = container_of(n, struct dict_entry, value);
|
||||
if (tree_de == de)
|
||||
HA_RWLOCK_WRUNLOCK(DICT_LOCK, &d->rwlock);
|
||||
else {
|
||||
/* another entry was already there, we'll return it, kill
|
||||
* ours and bump the other's refcount before returning it.
|
||||
*/
|
||||
HA_ATOMIC_INC(&tree_de->refcount);
|
||||
HA_RWLOCK_WRUNLOCK(DICT_LOCK, &d->rwlock);
|
||||
HA_RWLOCK_WRUNLOCK(DICT_LOCK, &d->rwlock);
|
||||
if (n != &de->value) {
|
||||
free_dict_entry(de);
|
||||
de = container_of(n, struct dict_entry, value);
|
||||
}
|
||||
return tree_de;
|
||||
|
||||
return de;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -122,11 +117,10 @@ void dict_entry_unref(struct dict *d, struct dict_entry *de)
|
|||
if (!de)
|
||||
return;
|
||||
|
||||
HA_RWLOCK_WRLOCK(DICT_LOCK, &d->rwlock);
|
||||
if (HA_ATOMIC_SUB_FETCH(&de->refcount, 1) != 0) {
|
||||
HA_RWLOCK_WRUNLOCK(DICT_LOCK, &d->rwlock);
|
||||
if (HA_ATOMIC_SUB_FETCH(&de->refcount, 1) != 0)
|
||||
return;
|
||||
}
|
||||
|
||||
HA_RWLOCK_WRLOCK(DICT_LOCK, &d->rwlock);
|
||||
ebpt_delete(&de->value);
|
||||
HA_RWLOCK_WRUNLOCK(DICT_LOCK, &d->rwlock);
|
||||
|
||||
|
|
|
|||
|
|
@ -1926,37 +1926,20 @@ static void dump_registered_keywords(void)
|
|||
|
||||
/* Generate a random cluster-secret in case the setting is not provided in the
|
||||
* configuration. This allows to use features which rely on it albeit with some
|
||||
* limitations. The function doesn't (solely) use ha_random64() because this
|
||||
* secret is permanent, and ha_random64() can easily be leaked at various
|
||||
* places.
|
||||
* limitations.
|
||||
*/
|
||||
static void generate_random_cluster_secret()
|
||||
{
|
||||
/* used as a default random cluster-secret if none defined. */
|
||||
union {
|
||||
uint64_t by64[2];
|
||||
uint32_t by32[4];
|
||||
uchar by8[16];
|
||||
} rand;
|
||||
uint64_t rand;
|
||||
|
||||
/* The caller must not overwrite an already defined secret. */
|
||||
BUG_ON(cluster_secret_isset);
|
||||
BUG_ON(sizeof(global.cluster_secret) != sizeof(rand));
|
||||
|
||||
#ifdef USE_OPENSSL
|
||||
if (RAND_bytes(rand.by8, sizeof(rand.by8)) != 1)
|
||||
#endif
|
||||
{
|
||||
/* no SSL or not working, fall back to other sources */
|
||||
rand.by64[0] = ha_random64();
|
||||
rand.by64[1] = ha_random64();
|
||||
rand.by32[0] ^= ((random() & 0x00ffff00) << 8) | ((random() & 0x00ffff00) >> 8);
|
||||
rand.by32[1] ^= ((random() & 0x00ffff00) << 8) | ((random() & 0x00ffff00) >> 8);
|
||||
rand.by32[2] ^= ((random() & 0x00ffff00) << 8) | ((random() & 0x00ffff00) >> 8);
|
||||
rand.by32[3] ^= ((random() & 0x00ffff00) << 8) | ((random() & 0x00ffff00) >> 8);
|
||||
}
|
||||
|
||||
rand = ha_random64();
|
||||
memcpy(global.cluster_secret, &rand, sizeof(rand));
|
||||
rand = ha_random64();
|
||||
memcpy(global.cluster_secret + sizeof(rand), &rand, sizeof(rand));
|
||||
cluster_secret_isset = 1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -788,7 +788,7 @@ static void hstream_parse_uri(struct ist uri, struct hstream *hs)
|
|||
} while (*next);
|
||||
|
||||
if (use_rand)
|
||||
result = ((long long)statistical_prng() * result) / 0xFFFFFFFFU;
|
||||
result = ((long long)ha_random64() * result) / ((long long)RAND_MAX + 1);
|
||||
|
||||
switch (*arg) {
|
||||
case 's':
|
||||
|
|
|
|||
|
|
@ -2949,20 +2949,20 @@ __LJMP static int hlua_socket_receive_yield(struct lua_State *L, int status, lua
|
|||
|
||||
/* remove final \r\n. */
|
||||
if (nblk == 1) {
|
||||
if (len1 && blk1[len1-1] == '\n') {
|
||||
if (blk1[len1-1] == '\n') {
|
||||
len1--;
|
||||
skip_at_end++;
|
||||
if (len1 && blk1[len1-1] == '\r') {
|
||||
if (blk1[len1-1] == '\r') {
|
||||
len1--;
|
||||
skip_at_end++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (len2 && blk2[len2-1] == '\n') {
|
||||
if (blk2[len2-1] == '\n') {
|
||||
len2--;
|
||||
skip_at_end++;
|
||||
if (len2 && blk2[len2-1] == '\r') {
|
||||
if (blk2[len2-1] == '\r') {
|
||||
len2--;
|
||||
skip_at_end++;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3319,7 +3319,7 @@ struct ist *build_log_header(struct log_header hdr, size_t *nbelem)
|
|||
break;
|
||||
}
|
||||
else if (metadata && metadata[LOG_META_TIME].len >= LOG_ISOTIME_MINLEN) {
|
||||
uint month;
|
||||
int month;
|
||||
char *timestamp = metadata[LOG_META_TIME].ptr;
|
||||
|
||||
/* iso time always begins like this: '1970-01-01T00:00:00' */
|
||||
|
|
@ -5499,7 +5499,7 @@ void parse_log_message(char *buf, size_t buflen, int *level, int *facility,
|
|||
return;
|
||||
fac_level = 10*fac_level + (*p - '0');
|
||||
p++;
|
||||
if ((p - buf) >= buflen)
|
||||
if ((p - buf) > buflen)
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -6743,7 +6743,6 @@ int cfg_parse_log_profile(const char *file, int linenum, char **args, int kwm)
|
|||
SMP_VAL_FE_LOG_END, &errmsg)) {
|
||||
ha_alert("Parsing [%s:%d]: failed to parse logformat: %s.\n",
|
||||
file, linenum, errmsg);
|
||||
lf_expr_deinit(target_lf);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
}
|
||||
|
|
|
|||
14
src/mux_h2.c
14
src/mux_h2.c
|
|
@ -6236,13 +6236,6 @@ next_frame:
|
|||
|
||||
/* Skip StreamDep and weight for now (we don't support PRIORITY) */
|
||||
if (h2c->dff & H2_F_HEADERS_PRIORITY) {
|
||||
if (flen < 5) {
|
||||
h2c_report_glitch(h2c, 1, "too short PRIORITY frame");
|
||||
TRACE_STATE("too short PRIORITY frame", H2_EV_RX_FRAME|H2_EV_RX_HDR|H2_EV_H2C_ERR|H2_EV_PROTO_ERR, h2c->conn);
|
||||
h2c_error(h2c, H2_ERR_FRAME_SIZE_ERROR);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (read_n32(hdrs) == h2c->dsi) {
|
||||
/* RFC7540#5.3.1 : stream dep may not depend on itself */
|
||||
h2c_report_glitch(h2c, 1, "PRIORITY frame referencing itself");
|
||||
|
|
@ -6252,6 +6245,13 @@ next_frame:
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (flen < 5) {
|
||||
h2c_report_glitch(h2c, 1, "too short PRIORITY frame");
|
||||
TRACE_STATE("too short PRIORITY frame", H2_EV_RX_FRAME|H2_EV_RX_HDR|H2_EV_H2C_ERR|H2_EV_PROTO_ERR, h2c->conn);
|
||||
h2c_error(h2c, H2_ERR_FRAME_SIZE_ERROR);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
hdrs += 5; // stream dep = 4, weight = 1
|
||||
flen -= 5;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -447,8 +447,8 @@ static size_t tcp_fullhdr_find_opt(const struct sample *smp, uint8_t opt)
|
|||
/* kind1 = NOP and is a single byte, others have a length field */
|
||||
if (smp->data.u.str.area[next] == 1)
|
||||
next++;
|
||||
else if (next + 1 < len && smp->data.u.str.area[next + 1] > 1)
|
||||
next += (uchar)smp->data.u.str.area[next + 1];
|
||||
else if (next + 1 < len)
|
||||
next += smp->data.u.str.area[next + 1];
|
||||
else
|
||||
break;
|
||||
if (smp->data.u.str.area[curr] == opt && next <= len)
|
||||
|
|
@ -605,7 +605,7 @@ static int sample_conv_tcp_options_list(const struct arg *arg_p, struct sample *
|
|||
/* kind1 = NOP and is a single byte, others have a length field */
|
||||
if (smp->data.u.str.area[ofs] == 1)
|
||||
ofs++;
|
||||
else if (ofs + 1 < len && smp->data.u.str.area[ofs + 1] > 1)
|
||||
else if (ofs + 1 < len && smp->data.u.str.area[ofs + 1])
|
||||
ofs += (uchar)smp->data.u.str.area[ofs + 1];
|
||||
else
|
||||
break;
|
||||
|
|
@ -780,7 +780,7 @@ static int sample_conv_ip_fp(const struct arg *arg_p, struct sample *smp, void *
|
|||
/* kind1 = NOP and is a single byte, others have a length field */
|
||||
if (smp->data.u.str.area[ofs] == 1)
|
||||
next = ofs + 1;
|
||||
else if ((ofs + 1 < tcplen) && smp->data.u.str.area[ofs + 1] > 1)
|
||||
else if ((ofs + 1 < tcplen) && smp->data.u.str.area[ofs + 1]) /* optlen 0 will cause an infinite loop */
|
||||
next = ofs + (uchar)smp->data.u.str.area[ofs + 1];
|
||||
else
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@
|
|||
#include <haproxy/uri_auth.h>
|
||||
|
||||
/* Lock to ensure multiple backends deletion concurrently is safe */
|
||||
__decl_spinlock(proxies_del_lock);
|
||||
static __decl_spinlock(proxies_del_lock);
|
||||
|
||||
int listeners; /* # of proxy listeners, set by cfgparse */
|
||||
struct proxy *proxies_list = NULL; /* list of main proxies */
|
||||
|
|
|
|||
|
|
@ -70,10 +70,6 @@ static int qmux_parse_frm(struct qcc *qcc, struct buffer *buf)
|
|||
struct qf_reset_stream *rst_frm = &frm.reset_stream;
|
||||
qcc_recv_reset_stream(qcc, rst_frm->id, rst_frm->app_error_code, rst_frm->final_size);
|
||||
}
|
||||
else if (frm.type == QUIC_FT_STOP_SENDING) {
|
||||
struct qf_stop_sending *ss_frm = &frm.stop_sending;
|
||||
qcc_recv_stop_sending(qcc, ss_frm->id, ss_frm->app_error_code);
|
||||
}
|
||||
else if (frm.type == QUIC_FT_MAX_DATA) {
|
||||
struct qf_max_data *md_frm = &frm.max_data;
|
||||
qcc_recv_max_data(qcc, md_frm->max_data);
|
||||
|
|
@ -86,26 +82,13 @@ static int qmux_parse_frm(struct qcc *qcc, struct buffer *buf)
|
|||
struct qf_max_streams *ms_frm = &frm.max_streams_bidi;
|
||||
qcc_recv_max_streams(qcc, ms_frm->max_streams, 1);
|
||||
}
|
||||
else if (frm.type == QUIC_FT_MAX_STREAMS_UNI) {
|
||||
struct qf_max_streams *ms_frm = &frm.max_streams_uni;
|
||||
qcc_recv_max_streams(qcc, ms_frm->max_streams, 0);
|
||||
}
|
||||
else if (frm.type == QUIC_FT_DATA_BLOCKED ||
|
||||
frm.type == QUIC_FT_STREAM_DATA_BLOCKED ||
|
||||
frm.type == QUIC_FT_STREAMS_BLOCKED_BIDI ||
|
||||
frm.type == QUIC_FT_STREAMS_BLOCKED_UNI) {
|
||||
/* TODO */
|
||||
CHECK_IF("received flow control blocked frame not yet handled in QMux");
|
||||
}
|
||||
else if (frm.type == QUIC_FT_PADDING) {
|
||||
CHECK_IF("received padding frame not yet handled in QMux");
|
||||
}
|
||||
else if (frm.type == QUIC_FT_CONNECTION_CLOSE ||
|
||||
frm.type == QUIC_FT_CONNECTION_CLOSE_APP) {
|
||||
CHECK_IF("received connection_close frame not yet handled in QMux");
|
||||
}
|
||||
else {
|
||||
/* qmux_is_frm_valid() must prevent this */
|
||||
ABORT_NOW();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -378,7 +378,7 @@ int quic_get_cid_tid(const unsigned char *cid, size_t cid_len,
|
|||
|
||||
tree = &quic_fe_cid_trees[quic_cid_tree_idx(&derive_cid)];
|
||||
HA_RWLOCK_RDLOCK(QC_CID_LOCK, &tree->lock);
|
||||
node = ebmb_lookup(&tree->root, derive_cid.data, derive_cid.len);
|
||||
node = ebmb_lookup(&tree->root, cid, cid_len);
|
||||
if (node) {
|
||||
conn_id = ebmb_entry(node, struct quic_connection_id, node);
|
||||
cid_tid = HA_ATOMIC_LOAD(&conn_id->tid);
|
||||
|
|
|
|||
|
|
@ -444,7 +444,7 @@ INITCALL0(STG_REGISTER, regex_register_build_options);
|
|||
#ifdef USE_PCRE2
|
||||
static int init_pcre2_per_thread(void)
|
||||
{
|
||||
local_pcre2_match = pcre2_match_data_create(MAX_MATCH, NULL);
|
||||
local_pcre2_match = pcre2_match_data_create(MAX_MATCH - 1, NULL);
|
||||
if (!local_pcre2_match) {
|
||||
ha_alert("Failed to allocate PCRE2 match data context for thread %u.\n", tid);
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@ struct show_resolvers_ctx {
|
|||
};
|
||||
|
||||
/* returns the currently accepted address families as a combination of
|
||||
* RSLV_ACCEPT_IPV4 and RSLV_ACCEPT_IPV6 only. It will dynamically adapt
|
||||
* RSLV_ACCEPT_IPV4 and RSLV_ACCEPT_IPV6 only. It will dynamically adapt adapt
|
||||
* the IPv6 status to sock_inet6_seems_reachable if RSLV_AUTO_FAMILY is set,
|
||||
* otherwise returns the relevant bits of resolv_accept_families.
|
||||
*/
|
||||
|
|
@ -509,7 +509,7 @@ resolv_run_resolution(struct resolv_resolution *resolution)
|
|||
return 0;
|
||||
|
||||
/* Check if a resolution has already been started for this server return
|
||||
* directly to avoid resolution pile up. */
|
||||
* directly to avoid resolution pill up. */
|
||||
if (resolution->step != RSLV_STEP_NONE)
|
||||
return 0;
|
||||
|
||||
|
|
@ -1236,7 +1236,8 @@ static int resolv_validate_dns_response(unsigned char *resp, unsigned char *bufe
|
|||
if (reader + 4 > bufend)
|
||||
goto invalid_resp;
|
||||
|
||||
answer_record->ttl = read_n32(reader);
|
||||
answer_record->ttl = reader[0] * 16777216 + reader[1] * 65536
|
||||
+ reader[2] * 256 + reader[3];
|
||||
reader += 4;
|
||||
|
||||
/* Now reading data len */
|
||||
|
|
@ -1497,7 +1498,8 @@ static int resolv_validate_dns_response(unsigned char *resp, unsigned char *bufe
|
|||
if (reader + 4 > bufend)
|
||||
goto invalid_resp;
|
||||
|
||||
answer_record->ttl = read_n32(reader);
|
||||
answer_record->ttl = reader[0] * 16777216 + reader[1] * 65536
|
||||
+ reader[2] * 256 + reader[3];
|
||||
reader += 4;
|
||||
|
||||
/* Now reading data len */
|
||||
|
|
@ -1597,6 +1599,7 @@ static int resolv_validate_dns_response(unsigned char *resp, unsigned char *bufe
|
|||
tmp_record->ar_item == NULL &&
|
||||
memcmp(tmp_record->data.target, answer_record->name, tmp_record->data_len) == 0) {
|
||||
/* Always use the received additional record to refresh info */
|
||||
pool_free(resolv_answer_item_pool, tmp_record->ar_item);
|
||||
tmp_record->ar_item = answer_record;
|
||||
answer_record = NULL;
|
||||
break;
|
||||
|
|
@ -1852,15 +1855,7 @@ int resolv_dn_label_to_str(const char *dn, int dn_len, char *str, int str_len)
|
|||
|
||||
ptr = str;
|
||||
for (i = 0; i < dn_len; ++i) {
|
||||
sz = (unsigned char)dn[i];
|
||||
|
||||
if (!sz)
|
||||
break;
|
||||
|
||||
/* Check str_len adding 1 for the dot if (i!=0) and 1 for null terminator */
|
||||
if (str_len < sz+i+(!!i)+1)
|
||||
return -1;
|
||||
|
||||
sz = dn[i];
|
||||
if (i)
|
||||
*ptr++ = '.';
|
||||
/* copy the string at i+1 to lower case */
|
||||
|
|
|
|||
|
|
@ -2150,11 +2150,11 @@ static int sample_conv_be2hex_check(struct arg *args, struct sample_conv *conv,
|
|||
*/
|
||||
static int sample_conv_be2hex(const struct arg *args, struct sample *smp, void *private)
|
||||
{
|
||||
struct buffer *trash = get_trash_chunk_sz(smp->data.u.str.data * 2);
|
||||
struct buffer *trash = get_trash_chunk_sz(smp->data.u.str.data);
|
||||
int chunk_size = args[1].data.sint;
|
||||
const int last = args[2].data.sint ? smp->data.u.str.data - chunk_size + 1 : smp->data.u.str.data;
|
||||
int i;
|
||||
size_t max_size;
|
||||
int max_size;
|
||||
int ptr = 0;
|
||||
unsigned char c;
|
||||
|
||||
|
|
@ -2163,9 +2163,7 @@ static int sample_conv_be2hex(const struct arg *args, struct sample *smp, void *
|
|||
trash->data = 0;
|
||||
if (args[0].data.str.data == 0 && args[2].data.sint == 0)
|
||||
chunk_size = smp->data.u.str.data;
|
||||
if (2 * (size_t)chunk_size > trash->size)
|
||||
return 0;
|
||||
max_size = trash->size - 2 * (size_t)chunk_size;
|
||||
max_size = trash->size - 2 * chunk_size;
|
||||
|
||||
while (ptr < last && trash->data <= max_size) {
|
||||
if (ptr) {
|
||||
|
|
|
|||
|
|
@ -241,17 +241,14 @@ int session_accept_fd(struct connection *cli_conn)
|
|||
if (l->bind_conf->options & BC_O_ACC_CIP)
|
||||
cli_conn->flags |= CO_FL_ACCEPT_CIP;
|
||||
|
||||
if (l->bind_conf->mux_proto && l->bind_conf->mux_proto->init_xprt == XPRT_QMUX)
|
||||
cli_conn->flags |= (CO_FL_QMUX_RECV|CO_FL_QMUX_SEND);
|
||||
|
||||
/* Add the handshake pseudo-XPRT */
|
||||
if (cli_conn->flags & (CO_FL_ACCEPT_PROXY | CO_FL_ACCEPT_CIP)) {
|
||||
if (xprt_add_hs(cli_conn) != 0)
|
||||
goto out_free_conn;
|
||||
}
|
||||
|
||||
/* Add handshake layer prior to MUX init if required. Does nothing if SSL layer is active though. */
|
||||
if (l->bind_conf->mux_proto && l->bind_conf->mux_proto->init_xprt) {
|
||||
if (xprt_add_l6hs(cli_conn, l->bind_conf->mux_proto->init_xprt))
|
||||
goto out_free_conn;
|
||||
}
|
||||
}
|
||||
|
||||
/* Reversed conns already have an assigned session, do not recreate it. */
|
||||
|
|
@ -354,7 +351,7 @@ int session_accept_fd(struct connection *cli_conn)
|
|||
* v | | |
|
||||
* conn -- owner ---> task <-----+
|
||||
*/
|
||||
if (cli_conn->flags & (CO_FL_WAIT_XPRT | CO_FL_EARLY_SSL_HS | CO_FL_WAIT_XPRT_L6)) {
|
||||
if (cli_conn->flags & (CO_FL_WAIT_XPRT | CO_FL_EARLY_SSL_HS)) {
|
||||
int timeout;
|
||||
int clt_tmt = p->timeout.client;
|
||||
int hs_tmt = p->timeout.client_hs;
|
||||
|
|
|
|||
|
|
@ -356,10 +356,8 @@ int ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind
|
|||
ssl_ctx = (SSL_CTX *)lru->data;
|
||||
if (!ssl_ctx && lru) {
|
||||
ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
|
||||
if (!ssl_ctx) {
|
||||
HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
|
||||
if (!ssl_ctx)
|
||||
goto error;
|
||||
}
|
||||
lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
|
||||
}
|
||||
SSL_set_SSL_CTX(ssl, ssl_ctx);
|
||||
|
|
|
|||
|
|
@ -290,8 +290,6 @@ int ssl_sock_load_ocsp_response(struct buffer *ocsp_response,
|
|||
int ret = 1;
|
||||
#ifdef HAVE_ASN1_TIME_TO_TM
|
||||
struct tm nextupd_tm = {0};
|
||||
#else
|
||||
long expire = 0;
|
||||
#endif
|
||||
|
||||
resp = d2i_OCSP_RESPONSE(NULL, (const unsigned char **)&p,
|
||||
|
|
@ -393,12 +391,11 @@ int ssl_sock_load_ocsp_response(struct buffer *ocsp_response,
|
|||
}
|
||||
ocsp->expire = my_timegm(&nextupd_tm) - OCSP_MAX_RESPONSE_TIME_SKEW;
|
||||
#else
|
||||
expire = asn1_generalizedtime_to_epoch(nextupd) - OCSP_MAX_RESPONSE_TIME_SKEW;
|
||||
if (expire < 0) {
|
||||
ocsp->expire = asn1_generalizedtime_to_epoch(nextupd) - OCSP_MAX_RESPONSE_TIME_SKEW;
|
||||
if (ocsp->expire < 0) {
|
||||
memprintf(err, "OCSP single response: Invalid \"Next Update\" time");
|
||||
goto out;
|
||||
}
|
||||
ocsp->expire = expire;
|
||||
#endif
|
||||
|
||||
if (ocsp->expire < date.tv_sec) {
|
||||
|
|
|
|||
|
|
@ -6973,8 +6973,12 @@ struct task *ssl_sock_io_cb(struct task *t, void *context, unsigned int state)
|
|||
mux = !conn_is_back(conn) ?
|
||||
conn_select_mux_fe(conn) : conn_select_mux_be(conn);
|
||||
|
||||
if (mux->init_xprt) {
|
||||
ret = xprt_add_l6hs(conn, mux->init_xprt);
|
||||
if (ctx->conn->flags & (CO_FL_QMUX_RECV|CO_FL_QMUX_SEND) ||
|
||||
mux->init_xprt == XPRT_QMUX) {
|
||||
const struct xprt_ops *ops = xprt_get(XPRT_QMUX);
|
||||
void *xprt_ctx_hs = NULL;
|
||||
|
||||
ret = ops->init(conn, &xprt_ctx_hs);
|
||||
/* Frontend conn must be freed in case of XPRT init failure. */
|
||||
if (ret) {
|
||||
if (!conn_is_back(conn)) {
|
||||
|
|
@ -6986,7 +6990,15 @@ struct task *ssl_sock_io_cb(struct task *t, void *context, unsigned int state)
|
|||
goto leave;
|
||||
}
|
||||
|
||||
ret = conn_xprt_start(conn);
|
||||
ret = ops->add_xprt(conn, xprt_ctx_hs,
|
||||
conn->xprt_ctx, conn->xprt, NULL, NULL);
|
||||
BUG_ON(ret); /* xprt_qmux add_xprt always succeeds */
|
||||
|
||||
conn->xprt = ops;
|
||||
conn->xprt_ctx = xprt_ctx_hs;
|
||||
|
||||
ret = conn->xprt->start(conn, xprt_ctx_hs);
|
||||
BUG_ON(ret);
|
||||
}
|
||||
else {
|
||||
/* TODO MUX selection already performs by conn_select_mux_fe/be().
|
||||
|
|
|
|||
|
|
@ -834,8 +834,6 @@ enum tcpcheck_eval_ret tcpcheck_spop_expect_hello(struct check *check, struct tc
|
|||
goto invalid_frame;
|
||||
if (decode_varint(&ptr, end, &sz) == -1)
|
||||
goto invalid_frame;
|
||||
if (sz >= SPOP_ERR_ENTRIES)
|
||||
sz = SPOP_ERR_UNKNOWN;
|
||||
check->code = sz;
|
||||
}
|
||||
|
||||
|
|
@ -991,7 +989,7 @@ enum tcpcheck_eval_ret tcpcheck_agent_expect_reply(struct check *check, struct t
|
|||
const char *sc = NULL; /* maxconn */
|
||||
const char *err = NULL; /* first error to report */
|
||||
const char *wrn = NULL; /* first warning to report */
|
||||
char *cmd, *p, *end;
|
||||
char *cmd, *p;
|
||||
|
||||
TRACE_ENTER(CHK_EV_TCPCHK_EXP, check);
|
||||
|
||||
|
|
@ -1020,11 +1018,10 @@ enum tcpcheck_eval_ret tcpcheck_agent_expect_reply(struct check *check, struct t
|
|||
*/
|
||||
|
||||
p = b_head(&check->bi);
|
||||
end = b_tail(&check->bi);
|
||||
while (p < end && *p && *p != '\n' && *p != '\r')
|
||||
while (*p && *p != '\n' && *p != '\r')
|
||||
p++;
|
||||
|
||||
if (!*p || p == end) {
|
||||
if (!*p) {
|
||||
if (!last_read)
|
||||
goto wait_more_data;
|
||||
|
||||
|
|
|
|||
|
|
@ -12,9 +12,6 @@
|
|||
#include <haproxy/quic_frame.h>
|
||||
#include <haproxy/quic_tp-t.h>
|
||||
|
||||
/* Default protocol when not running over SSL layer. */
|
||||
#define XPRT_QMUX_DEFAULT_ALPN "h3"
|
||||
|
||||
struct xprt_qmux_ctx {
|
||||
struct connection *conn;
|
||||
struct wait_event wait_event;
|
||||
|
|
@ -210,7 +207,7 @@ struct task *xprt_qmux_io_cb(struct task *t, void *context, unsigned int state)
|
|||
|
||||
out:
|
||||
if ((conn->flags & CO_FL_ERROR) ||
|
||||
!(conn->flags & CO_FL_WAIT_XPRT_L6)) {
|
||||
!(conn->flags & (CO_FL_QMUX_RECV|CO_FL_QMUX_SEND))) {
|
||||
/* XPRT should be unsubscribed when transfer done or on error. */
|
||||
BUG_ON(ctx->wait_event.events);
|
||||
|
||||
|
|
@ -335,7 +332,7 @@ static void xprt_qmux_close(struct connection *conn, void *xprt_ctx)
|
|||
if (ctx->ops_lower && ctx->ops_lower->close)
|
||||
ctx->ops_lower->close(conn, ctx->ctx_lower);
|
||||
|
||||
conn->flags &= ~CO_FL_WAIT_XPRT_L6;
|
||||
conn->flags &= ~(CO_FL_QMUX_RECV|CO_FL_QMUX_SEND);
|
||||
|
||||
BUG_ON(conn->xprt_ctx != ctx);
|
||||
conn->xprt_ctx = ctx->ctx_lower;
|
||||
|
|
@ -349,14 +346,6 @@ static int xprt_qmux_get_alpn(const struct connection *conn, void *xprt_ctx,
|
|||
const char **str, int *len)
|
||||
{
|
||||
struct xprt_qmux_ctx *ctx = xprt_ctx;
|
||||
|
||||
/* Return a the default ALPN if lower layer is not able to negotiate it. */
|
||||
if (!ctx->ops_lower || !ctx->ops_lower->get_alpn) {
|
||||
*str = XPRT_QMUX_DEFAULT_ALPN;
|
||||
*len = strlen(XPRT_QMUX_DEFAULT_ALPN);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return ctx->ops_lower->get_alpn(conn, ctx->ctx_lower, str, len);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue