From: Willy Tarreau Date: Tue, 10 Nov 2026 10:19:20 +0000 (+0100) Subject: MINOR: mux: add sctl MUX_SCTL_GET_HDNG_FOUND/FIXED to report hardening results X-Git-Tag: v3.5-dev12~4 X-Git-Url: https://git.kaiwu.me/%7B@url%7D?a=commitdiff_plain;h=1a2e46898276718cc018beceb6c0429bb63bd2c8;p=haproxy.git MINOR: mux: add sctl MUX_SCTL_GET_HDNG_FOUND/FIXED to report hardening results The H1, H2 and H3 streams store in their http_hdng_chk what HTTP hardening conditions were met (found) and what rules were enforced (fixed). This adds two new mux stream controls to retrieve them as uint32_t, so that they can be reported by sample fetches and logged: - MUX_SCTL_GET_HDNG_FOUND returns hdng_chk.found - MUX_SCTL_GET_HDNG_FIXED returns hdng_chk.fixed They're implemented in the H1 and H2 muxes. The QUIC mux passes them to the application layer's sctl() after checking that it's H3, and h3_sctl() implements them. Other muxes return -1 as they don't support hardening. --- diff --git a/include/haproxy/connection-t.h b/include/haproxy/connection-t.h index 075152d2f..45c404fca 100644 --- a/include/haproxy/connection-t.h +++ b/include/haproxy/connection-t.h @@ -400,6 +400,8 @@ enum mux_sctl_type { MUX_SCTL_SID, /* Return the mux stream ID as output, as a signed 64bits integer */ MUX_SCTL_DBG_STR, /* takes a mux_sctl_dbg_str_ctx argument, reads flags and returns debug info */ MUX_SCTL_TEVTS, /* Return the termination events log of the mux stream */ + MUX_SCTL_GET_HDNG_FOUND, /* Return in output the HTTP_HRD_* hardening conditions met, as an uint32_t */ + MUX_SCTL_GET_HDNG_FIXED, /* Return in output the HTTP_HRD_* hardening rules enforced, as an uint32_t */ }; #define MUX_SCTL_DBG_STR_L_MUXS 0x00000001 // info from mux stream diff --git a/src/h3.c b/src/h3.c index 323952162..32a7055c2 100644 --- a/src/h3.c +++ b/src/h3.c @@ -3939,7 +3939,19 @@ static void h3_stats_inc_err_cnt(void *ctx, int err_code) */ static int h3_sctl(struct qcs *qcs, enum mux_sctl_type mux_sctl, void *output) { + const struct h3s *h3s = qcs->ctx; + switch (mux_sctl) { + case MUX_SCTL_GET_HDNG_FOUND: + if (!h3s) + return -1; + *((uint32_t *)output) = h3s->hdng_chk.found; + return 0; + case MUX_SCTL_GET_HDNG_FIXED: + if (!h3s) + return -1; + *((uint32_t *)output) = h3s->hdng_chk.fixed; + return 0; default: return -1; } diff --git a/src/mux_h1.c b/src/mux_h1.c index 032e1865d..55115878b 100644 --- a/src/mux_h1.c +++ b/src/mux_h1.c @@ -5770,6 +5770,12 @@ static int h1_sctl(struct stconn *sc, enum mux_sctl_type mux_sctl, void *output) return ret; case MUX_SCTL_TEVTS: return h1s->sd->term_evts_log; + case MUX_SCTL_GET_HDNG_FOUND: + *((uint32_t *)output) = h1s->hdng_chk.found; + return ret; + case MUX_SCTL_GET_HDNG_FIXED: + *((uint32_t *)output) = h1s->hdng_chk.fixed; + return ret; default: return -1; } diff --git a/src/mux_h2.c b/src/mux_h2.c index 39fd6cfb4..1a4fa4b5e 100644 --- a/src/mux_h2.c +++ b/src/mux_h2.c @@ -5809,6 +5809,12 @@ static int h2_sctl(struct stconn *sc, enum mux_sctl_type mux_sctl, void *output) return ret; case MUX_SCTL_TEVTS: return h2s->sd->term_evts_log; + case MUX_SCTL_GET_HDNG_FOUND: + *((uint32_t *)output) = h2s->hdng_chk.found; + return ret; + case MUX_SCTL_GET_HDNG_FIXED: + *((uint32_t *)output) = h2s->hdng_chk.fixed; + return ret; default: return -1; diff --git a/src/mux_quic.c b/src/mux_quic.c index ba9d45999..9a72d7ca5 100644 --- a/src/mux_quic.c +++ b/src/mux_quic.c @@ -4920,7 +4920,7 @@ static int qcm_ctl(struct connection *conn, enum mux_ctl_type mux_ctl, void *out static int qcm_sctl(struct stconn *sc, enum mux_sctl_type mux_sctl, void *output) { int ret = 0; - const struct qcs *qcs = __sc_mux_strm(sc); + struct qcs *qcs = __sc_mux_strm(sc); const struct qcc *qcc = qcs->qcc; const struct connection *conn = qcc->conn; union mux_sctl_dbg_str_ctx *dbg_ctx; @@ -4957,6 +4957,13 @@ static int qcm_sctl(struct stconn *sc, enum mux_sctl_type mux_sctl, void *output case MUX_SCTL_TEVTS: return qcs->sd->term_evts_log; + case MUX_SCTL_GET_HDNG_FOUND: + case MUX_SCTL_GET_HDNG_FIXED: + /* only known to the H3 layer */ + if (qcc->app_ops != &h3_ops || !qcc->app_ops->sctl) + return -1; + return qcc->app_ops->sctl(qcs, mux_sctl, output); + default: return -1; }