]> git.kaiwu.me - haproxy.git/commitdiff
MEDIUM: connections: Enforce mux protocol requirements
authorOlivier Houchard <ohouchard@haproxy.com>
Thu, 19 Mar 2026 14:00:41 +0000 (15:00 +0100)
committerOlivier Houchard <cognet@ci0.org>
Thu, 26 Mar 2026 14:09:13 +0000 (15:09 +0100)
When picking a mux, pay attention to its MX_FL_FRAMED. If it is set,
then it means we explicitely want QUIC, so don't use that mux for any
protocol that is not QUIC.

include/haproxy/connection.h
src/proxy.c
src/server.c
src/stream.c

index e311c8d129633188ae45e9c1bffe7ea2cc0f5609..03c3306ae37138eee85afa455defef3df3767dfb 100644 (file)
@@ -34,6 +34,7 @@
 #include <haproxy/listener-t.h>
 #include <haproxy/obj_type.h>
 #include <haproxy/pool-t.h>
+#include <haproxy/protocol.h>
 #include <haproxy/server.h>
 #include <haproxy/session-t.h>
 #include <haproxy/task-t.h>
@@ -609,13 +610,13 @@ void list_mux_proto(FILE *out);
  */
 static inline const struct mux_proto_list *conn_get_best_mux_entry(
         const struct ist mux_proto,
-        int proto_side, int proto_mode)
+        int proto_side, int proto_is_quic, int proto_mode)
 {
        struct mux_proto_list *item;
        struct mux_proto_list *fallback = NULL;
 
        list_for_each_entry(item, &mux_proto_list.list, list) {
-               if (!(item->side & proto_side) || !(item->mode & proto_mode))
+               if (!(item->side & proto_side) || !(item->mode & proto_mode) || (proto_is_quic && !(item->mux->flags & MX_FL_FRAMED)))
                        continue;
                if (istlen(mux_proto) && isteq(mux_proto, item->token))
                        return item;
@@ -640,7 +641,7 @@ static inline const struct mux_ops *conn_get_best_mux(struct connection *conn,
 {
        const struct mux_proto_list *item;
 
-       item = conn_get_best_mux_entry(mux_proto, proto_side, proto_mode);
+       item = conn_get_best_mux_entry(mux_proto, proto_side, proto_is_quic(conn->ctrl), proto_mode);
 
        return item ? item->mux : NULL;
 }
index 2efef109031fbc339971f0fafb1a7947120554b1..203f2ac09a60dbf7fb7a5811b7ac630539f96d16 100644 (file)
@@ -1676,11 +1676,17 @@ int proxy_finalize(struct proxy *px, int *err_code)
                }
 
                if (bind_conf->mux_proto) {
+                       int is_quic;
+
+                       if ((bind_conf->options & (BC_O_USE_SOCK_DGRAM | BC_O_USE_XPRT_STREAM)) == (BC_O_USE_SOCK_DGRAM | BC_O_USE_XPRT_STREAM))
+                               is_quic = 1;
+                       else
+                               is_quic = 0;
                        /* it is possible that an incorrect mux was referenced
                         * 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->token, PROTO_SIDE_FE, mode);
+                       mux_ent = conn_get_best_mux_entry(bind_conf->mux_proto->token, PROTO_SIDE_FE, is_quic, mode);
 
                        if (!mux_ent || !isteq(mux_ent->token, bind_conf->mux_proto->token)) {
                                ha_alert("%s '%s' : MUX protocol '%.*s' is not usable for 'bind %s' at [%s:%d].\n",
@@ -2879,7 +2885,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->token, PROTO_SIDE_BE, mode);
+               mux_ent = conn_get_best_mux_entry(newsrv->mux_proto->token, PROTO_SIDE_BE, srv_is_quic(newsrv), mode);
 
                if (!mux_ent || !isteq(mux_ent->token, newsrv->mux_proto->token)) {
                        ha_alert("%s '%s' : MUX protocol '%.*s' is not usable for server '%s' at [%s:%d].\n",
index 2a6f018173545e06602b859711b08ee96d397442..4368d70678a99287b41c6cc69ed02bb8fce6cad6 100644 (file)
@@ -6242,7 +6242,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->token, PROTO_SIDE_BE, proto_mode);
+               mux_ent = conn_get_best_mux_entry(srv->mux_proto->token, PROTO_SIDE_BE, srv_is_quic(srv), proto_mode);
 
                if (!mux_ent || !isteq(mux_ent->token, srv->mux_proto->token)) {
                        ha_alert("MUX protocol is not usable for server.\n");
index a83a4f68eb74c21ddb4767c201d1aab3d063c0d9..123f7096169c4b71ee88439721e559c566272059 100644 (file)
@@ -3289,7 +3289,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->token, PROTO_SIDE_FE, mode);
+               mux_ent = conn_get_best_mux_entry(mux_proto->token, PROTO_SIDE_FE, 0, mode);
                if (!mux_ent || !isteq(mux_ent->token, mux_proto->token)) {
                        memprintf(err, "MUX protocol '%.*s' is not compatible with the selected mode",
                                  (int)mux_proto->token.len, mux_proto->token.ptr);
@@ -3297,7 +3297,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, mode);
+               mux_ent = conn_get_best_mux_entry(IST_NULL, PROTO_SIDE_FE, 0, mode);
                if (!mux_ent) {
                        memprintf(err, "Unable to find compatible MUX protocol with the selected mode");
                        return 0;