MINOR: mux_h2: define config to disable h2 websocket support

Define a new global config statement named
"h2-workaround-bogus-websocket-clients".

This statement will disable the automatic announce of h2 websocket
support as specified in the RFC8441. This can be use to overcome clients
which fail to implement the relatively fresh RFC8441. Clients will in
his case automatically downgrade to http/1.1 for the websocket tunnel
if the haproxy configuration allows it.

This feature is relatively simple and can be backported up to 2.4, which
saw the introduction of h2 websocket support.

(cherry picked from commit befeae88e8c7e2cbc19a63420bfa7d67ec176342)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 174be6c..d28de2f 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -979,6 +979,7 @@
    - insecure-fork-wanted
    - insecure-setuid-wanted
    - issuers-chain-path
+   - h2-workaround-bogus-websocket-clients
    - localpeer
    - log
    - log-tag
@@ -1412,6 +1413,15 @@
   "issuers-chain-path" directory. All other certificates with the same issuer
   will share the chain in memory.
 
+h2-workaround-bogus-websocket-clients
+  This disables the announcement of the support for h2 websockets to clients.
+  This can be use to overcome clients which have issues when implementing the
+  relatively fresh RFC8441, such as Firefox 88. To allow clients to
+  automatically downgrade to http/1.1 for the websocket tunnel, specify h2
+  support on the bind line using "alpn" without an explicit "proto" keyword. If
+  this statement was previously activated, this can be disabled by prefixing
+  the keyword with "no'.
+
 localpeer <name>
   Sets the local instance's peer name. It will be ignored if the "-L"
   command line argument is specified or if used after "peers" section
diff --git a/include/haproxy/global-t.h b/include/haproxy/global-t.h
index 1bdbc1b..633bbb5 100644
--- a/include/haproxy/global-t.h
+++ b/include/haproxy/global-t.h
@@ -69,6 +69,7 @@
 #define GTUNE_FD_ET              (1<<18)
 #define GTUNE_SCHED_LOW_LATENCY  (1<<19)
 #define GTUNE_IDLE_POOL_SHARED   (1<<20)
+#define GTUNE_DISABLE_H2_WEBSOCKET (1<<21)
 
 /* SSL server verify mode */
 enum {
diff --git a/src/cfgparse-global.c b/src/cfgparse-global.c
index b539a97..c2a44d9 100644
--- a/src/cfgparse-global.c
+++ b/src/cfgparse-global.c
@@ -128,6 +128,14 @@
 		else
 			global.tune.options |=  GTUNE_SET_DUMPABLE;
 	}
+	else if (strcmp(args[0], "h2-workaround-bogus-websocket-clients") == 0) { /* "no h2-workaround-bogus-websocket-clients" or "h2-workaround-bogus-websocket-clients" */
+		if (alertif_too_many_args(0, file, linenum, args, &err_code))
+			goto out;
+		if (kwm == KWM_NO)
+			global.tune.options &= ~GTUNE_DISABLE_H2_WEBSOCKET;
+		else
+			global.tune.options |=  GTUNE_DISABLE_H2_WEBSOCKET;
+	}
 	else if (strcmp(args[0], "insecure-fork-wanted") == 0) { /* "no insecure-fork-wanted" or "insecure-fork-wanted" */
 		if (alertif_too_many_args(0, file, linenum, args, &err_code))
 			goto out;
diff --git a/src/mux_h2.c b/src/mux_h2.c
index 9cb6eba..fbc7963 100644
--- a/src/mux_h2.c
+++ b/src/mux_h2.c
@@ -1610,9 +1610,10 @@
 		chunk_memcat(&buf, "\x00\x02\x00\x00\x00\x00", 6);
 	}
 
-	/* rfc 8441 #3 SETTINGS_ENABLE_CONNECT_PROTOCOL=1
-	 * sent automatically */
-	chunk_memcat(&buf, "\x00\x08\x00\x00\x00\x01", 6);
+	/* rfc 8441 #3 SETTINGS_ENABLE_CONNECT_PROTOCOL=1,
+	 * sent automatically unless disabled in the global config */
+	if (!(global.tune.options & GTUNE_DISABLE_H2_WEBSOCKET))
+		chunk_memcat(&buf, "\x00\x08\x00\x00\x00\x01", 6);
 
 	if (h2_settings_header_table_size != 4096) {
 		char str[6] = "\x00\x01"; /* header_table_size */