diff --git a/include/haproxy/connection.h b/include/haproxy/connection.h index f73bb334c..dfd816344 100644 --- a/include/haproxy/connection.h +++ b/include/haproxy/connection.h @@ -668,6 +668,7 @@ void list_mux_proto(FILE *out); */ static inline const struct mux_proto_list *conn_get_best_mux_entry( const struct ist mux_proto, + const struct ist alpn, int proto_side, int proto_is_quic, int proto_mode) { struct mux_proto_list *item; @@ -679,6 +680,10 @@ static inline const struct mux_proto_list *conn_get_best_mux_entry( if (istlen(mux_proto) && isteq(mux_proto, item->mux_proto)) { return item; } + else if (istlen(alpn) && item->alpn && + strlen(item->alpn) == istlen(alpn) + 1 && + !memcmp(alpn.ptr, item->alpn + 1, istlen(alpn))) + return item; else if (!istlen(item->mux_proto)) { if (!fallback || (item->mode == proto_mode && fallback->mode != proto_mode)) fallback = item; @@ -696,11 +701,12 @@ static inline const struct mux_proto_list *conn_get_best_mux_entry( */ static inline const struct mux_ops *conn_get_best_mux(struct connection *conn, const struct ist mux_proto, + const struct ist alpn, int proto_side, int proto_mode) { const struct mux_proto_list *item; - item = conn_get_best_mux_entry(mux_proto, proto_side, proto_is_quic(conn->ctrl), proto_mode); + item = conn_get_best_mux_entry(mux_proto, alpn, proto_side, proto_is_quic(conn->ctrl), proto_mode); return item ? item->mux : NULL; } diff --git a/src/connection.c b/src/connection.c index 7112ef1cd..50fc6c457 100644 --- a/src/connection.c +++ b/src/connection.c @@ -282,6 +282,7 @@ int conn_upgrade_mux_fe(struct connection *conn, void *ctx, struct buffer *buf, struct ist mux_proto, int mode) { struct bind_conf *bind_conf = __objt_listener(conn->target)->bind_conf; + struct ist alpn = IST_NULL; const struct mux_ops *old_mux, *new_mux; void *old_mux_ctx; const char *alpn_str = NULL; @@ -289,9 +290,9 @@ int conn_upgrade_mux_fe(struct connection *conn, void *ctx, struct buffer *buf, if (!mux_proto.len) { conn_get_alpn(conn, &alpn_str, &alpn_len); - mux_proto = ist2(alpn_str, alpn_len); + alpn = ist2(alpn_str, alpn_len); } - new_mux = conn_get_best_mux(conn, mux_proto, PROTO_SIDE_FE, mode); + new_mux = conn_get_best_mux(conn, mux_proto, alpn, PROTO_SIDE_FE, mode); old_mux = conn->mux; /* No mux found */ @@ -330,14 +331,14 @@ int conn_install_mux_fe(struct connection *conn, void *ctx) if (bind_conf->mux_proto) mux_ops = bind_conf->mux_proto->mux; else { - struct ist mux_proto; + struct ist alpn; const char *alpn_str = NULL; int alpn_len = 0; int mode = conn_pr_mode_to_proto_mode(bind_conf->frontend->mode); conn_get_alpn(conn, &alpn_str, &alpn_len); - mux_proto = ist2(alpn_str, alpn_len); - mux_ops = conn_get_best_mux(conn, mux_proto, PROTO_SIDE_FE, mode); + alpn = ist2(alpn_str, alpn_len); + mux_ops = conn_get_best_mux(conn, IST_NULL, alpn, PROTO_SIDE_FE, mode); if (!mux_ops) return -1; } @@ -380,7 +381,7 @@ int conn_install_mux_be(struct connection *conn, void *ctx, struct session *sess mux_ops = force_mux_ops; } else { - struct ist mux_proto; + struct ist alpn; const char *alpn_str = NULL; int alpn_len = 0; int mode = conn_pr_mode_to_proto_mode(prx->mode); @@ -391,9 +392,9 @@ int conn_install_mux_be(struct connection *conn, void *ctx, struct session *sess alpn_len = strlen(alpn_str); } } - mux_proto = ist2(alpn_str, alpn_len); + alpn = ist2(alpn_str, alpn_len); - mux_ops = conn_get_best_mux(conn, mux_proto, PROTO_SIDE_BE, mode); + mux_ops = conn_get_best_mux(conn, IST_NULL, alpn, PROTO_SIDE_BE, mode); if (!mux_ops) return -1; } @@ -434,15 +435,15 @@ int conn_install_mux_chk(struct connection *conn, void *ctx, struct session *ses if (check->mux_proto) mux_ops = check->mux_proto->mux; else { - struct ist mux_proto; + struct ist alpn; const char *alpn_str = NULL; int alpn_len = 0; int mode = tcpchk_rules_type_to_proto_mode(check->tcpcheck->rs->flags); conn_get_alpn(conn, &alpn_str, &alpn_len); - mux_proto = ist2(alpn_str, alpn_len); + alpn = ist2(alpn_str, alpn_len); - mux_ops = conn_get_best_mux(conn, mux_proto, PROTO_SIDE_BE, mode); + mux_ops = conn_get_best_mux(conn, IST_NULL, alpn, PROTO_SIDE_BE, mode); if (!mux_ops) return -1; } diff --git a/src/proxy.c b/src/proxy.c index c12ffdf55..f0667228c 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -1689,7 +1689,7 @@ int proxy_finalize(struct proxy *px, int *err_code) * due to the proxy's mode not being taken into account * on first pass. Let's adjust it now. */ - mux_ent = conn_get_best_mux_entry(bind_conf->mux_proto->mux_proto, PROTO_SIDE_FE, is_quic, mode); + mux_ent = conn_get_best_mux_entry(bind_conf->mux_proto->mux_proto, IST_NULL, PROTO_SIDE_FE, is_quic, mode); if (!mux_ent || !isteq(mux_ent->mux_proto, bind_conf->mux_proto->mux_proto)) { ha_alert("%s '%s' : MUX protocol '%.*s' is not usable for 'bind %s' at [%s:%d].\n", @@ -2849,7 +2849,7 @@ int proxy_finalize(struct proxy *px, int *err_code) * due to the proxy's mode not being taken into account * on first pass. Let's adjust it now. */ - mux_ent = conn_get_best_mux_entry(newsrv->mux_proto->mux_proto, PROTO_SIDE_BE, srv_is_quic(newsrv), mode); + mux_ent = conn_get_best_mux_entry(newsrv->mux_proto->mux_proto, IST_NULL, PROTO_SIDE_BE, srv_is_quic(newsrv), mode); if (!mux_ent || !isteq(mux_ent->mux_proto, newsrv->mux_proto->mux_proto)) { ha_alert("%s '%s' : MUX protocol '%.*s' is not usable for server '%s' at [%s:%d].\n", diff --git a/src/server.c b/src/server.c index 4d52556e0..94105518c 100644 --- a/src/server.c +++ b/src/server.c @@ -6278,7 +6278,7 @@ static int cli_parse_add_server(char **args, char *payload, struct appctx *appct int proto_mode = conn_pr_mode_to_proto_mode(be->mode); const struct mux_proto_list *mux_ent; - mux_ent = conn_get_best_mux_entry(srv->mux_proto->mux_proto, PROTO_SIDE_BE, srv_is_quic(srv), proto_mode); + mux_ent = conn_get_best_mux_entry(srv->mux_proto->mux_proto, IST_NULL, PROTO_SIDE_BE, srv_is_quic(srv), proto_mode); if (!mux_ent || !isteq(mux_ent->mux_proto, srv->mux_proto->mux_proto)) { ha_alert("MUX protocol is not usable for server.\n"); diff --git a/src/stream.c b/src/stream.c index fd27b9cf6..73feb7ebf 100644 --- a/src/stream.c +++ b/src/stream.c @@ -3268,7 +3268,7 @@ static int check_tcp_switch_stream_mode(struct act_rule *rule, struct proxy *px, px->options |= PR_O_HTTP_UPG; if (mux_proto) { - mux_ent = conn_get_best_mux_entry(mux_proto->mux_proto, PROTO_SIDE_FE, 0, mode); + mux_ent = conn_get_best_mux_entry(mux_proto->mux_proto, IST_NULL, PROTO_SIDE_FE, 0, mode); if (!mux_ent || !isteq(mux_ent->mux_proto, mux_proto->mux_proto)) { memprintf(err, "MUX protocol '%.*s' is not compatible with the selected mode", (int)mux_proto->mux_proto.len, mux_proto->mux_proto.ptr); @@ -3276,7 +3276,7 @@ static int check_tcp_switch_stream_mode(struct act_rule *rule, struct proxy *px, } } else { - mux_ent = conn_get_best_mux_entry(IST_NULL, PROTO_SIDE_FE, 0, mode); + mux_ent = conn_get_best_mux_entry(IST_NULL, IST_NULL, PROTO_SIDE_FE, 0, mode); if (!mux_ent) { memprintf(err, "Unable to find compatible MUX protocol with the selected mode"); return 0; diff --git a/src/tcpcheck.c b/src/tcpcheck.c index d354291f1..b7203d1fa 100644 --- a/src/tcpcheck.c +++ b/src/tcpcheck.c @@ -1570,7 +1570,7 @@ enum tcpcheck_eval_ret tcpcheck_eval_connect(struct check *check, struct tcpchec else { int mode = tcpchk_rules_type_to_proto_mode(check->tcpcheck->rs->flags); - mux_ops = conn_get_best_mux(conn, IST_NULL, PROTO_SIDE_BE, mode); + mux_ops = conn_get_best_mux(conn, IST_NULL, IST_NULL, PROTO_SIDE_BE, mode); } if (mux_ops && conn_install_mux(conn, mux_ops, check->sc, proxy, check->sess) < 0) { TRACE_ERROR("failed to install mux", CHK_EV_TCPCHK_CONN|CHK_EV_TCPCHK_ERR, check);