MINOR: protocol: move the global reuseport flag to the protocols

Some protocol support SO_REUSEPORT and others not. Some have such a
limitation in the kernel, and others in haproxy itself (e.g. sock_unix
cannot support multiple bindings since each one will unbind the previous
one). Also it's really protocol-dependent and not just family-dependent
because on Linux for some time it was supported for TCP and not UDP.

Let's move the definition to the protocols instead. Now it's preset in
tcp/udp/quic when SO_REUSEPORT is defined, and is otherwise left unset.
The enabled() config condition test validates IPv4 (generally sufficient),
and -dR / noreuseport all protocols at once.
diff --git a/include/haproxy/global-t.h b/include/haproxy/global-t.h
index af7f26c..3a7b53b 100644
--- a/include/haproxy/global-t.h
+++ b/include/haproxy/global-t.h
@@ -58,7 +58,7 @@
 /* platform-specific options */
 #define GTUNE_USE_SPLICE         (1<<4)
 #define GTUNE_USE_GAI            (1<<5)
-#define GTUNE_USE_REUSEPORT      (1<<6)
+/* unused: (1<<6) */
 #define GTUNE_RESOLVE_DONTFAIL   (1<<7)
 
 #define GTUNE_SOCKET_TRANSFER	 (1<<8)
diff --git a/include/haproxy/protocol-t.h b/include/haproxy/protocol-t.h
index aa8aa66..eec65fe 100644
--- a/include/haproxy/protocol-t.h
+++ b/include/haproxy/protocol-t.h
@@ -64,6 +64,9 @@
 #define CONNECT_DELACK_ALWAYS                   0x00000004 /* Use a delayed ACK */
 #define CONNECT_CAN_USE_TFO                     0x00000008 /* We can use TFO for this connection */
 
+/* Flags for protocol->flags */
+#define PROTO_F_REUSEPORT_SUPPORTED             0x00000001 /* SO_REUSEPORT is supported */
+
 /* protocol families define standard functions acting on a given address family
  * for a socket implementation, such as AF_INET/PF_INET for example.
  */
diff --git a/src/cfgcond.c b/src/cfgcond.c
index 89036ad..117cf6c 100644
--- a/src/cfgcond.c
+++ b/src/cfgcond.c
@@ -14,6 +14,7 @@
 #include <haproxy/arg.h>
 #include <haproxy/cfgcond.h>
 #include <haproxy/global.h>
+#include <haproxy/proto_tcp.h>
 #include <haproxy/tools.h>
 
 /* supported condition predicates */
@@ -195,7 +196,7 @@
 	else if (strcmp(str, "GETADDRINFO") == 0)
 		return !!(global.tune.options & GTUNE_USE_GAI);
 	else if (strcmp(str, "REUSEPORT") == 0)
-		return !!(global.tune.options & GTUNE_USE_REUSEPORT);
+		return !!(proto_tcpv4.flags & PROTO_F_REUSEPORT_SUPPORTED);
 	else if (strcmp(str, "FAST-FORWARD") == 0)
 		return !!(global.tune.options & GTUNE_USE_FAST_FWD);
 	else if (strcmp(str, "SERVER-SSL-VERIFY-NONE") == 0)
diff --git a/src/cfgparse-global.c b/src/cfgparse-global.c
index e46672e..76d1769 100644
--- a/src/cfgparse-global.c
+++ b/src/cfgparse-global.c
@@ -20,6 +20,7 @@
 #include <haproxy/global.h>
 #include <haproxy/log.h>
 #include <haproxy/peers.h>
+#include <haproxy/protocol.h>
 #include <haproxy/tools.h>
 
 /* some keywords that are still being parsed using strcmp() and are not
@@ -171,7 +172,7 @@
 	else if (strcmp(args[0], "noreuseport") == 0) {
 		if (alertif_too_many_args(0, file, linenum, args, &err_code))
 			goto out;
-		global.tune.options &= ~GTUNE_USE_REUSEPORT;
+		protocol_clrf_all(PROTO_F_REUSEPORT_SUPPORTED);
 	}
 	else if (strcmp(args[0], "quiet") == 0) {
 		if (alertif_too_many_args(0, file, linenum, args, &err_code))
diff --git a/src/haproxy.c b/src/haproxy.c
index 5306113..b1574ab 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -1589,9 +1589,6 @@
 #if defined(USE_GETADDRINFO)
 	global.tune.options |= GTUNE_USE_GAI;
 #endif
-#if defined(SO_REUSEPORT)
-	global.tune.options |= GTUNE_USE_REUSEPORT;
-#endif
 #ifdef USE_THREAD
 	global.tune.options |= GTUNE_IDLE_POOL_SHARED;
 #endif
@@ -1650,7 +1647,7 @@
 #endif
 #if defined(SO_REUSEPORT)
 			else if (*flag == 'd' && flag[1] == 'R')
-				global.tune.options &= ~GTUNE_USE_REUSEPORT;
+				protocol_clrf_all(PROTO_F_REUSEPORT_SUPPORTED);
 #endif
 			else if (*flag == 'd' && flag[1] == 'F')
 				global.tune.options &= ~GTUNE_USE_FAST_FWD;
diff --git a/src/proto_quic.c b/src/proto_quic.c
index 7658329..22776cd 100644
--- a/src/proto_quic.c
+++ b/src/proto_quic.c
@@ -105,6 +105,9 @@
 	.default_iocb   = quic_lstnr_sock_fd_iocb,
 	.receivers      = LIST_HEAD_INIT(proto_quic4.receivers),
 	.nb_receivers   = 0,
+#ifdef SO_REUSEPORT
+	.flags          = PROTO_F_REUSEPORT_SUPPORTED,
+#endif
 };
 
 INITCALL1(STG_REGISTER, protocol_register, &proto_quic4);
@@ -146,6 +149,9 @@
 	.default_iocb   = quic_lstnr_sock_fd_iocb,
 	.receivers      = LIST_HEAD_INIT(proto_quic6.receivers),
 	.nb_receivers   = 0,
+#ifdef SO_REUSEPORT
+	.flags          = PROTO_F_REUSEPORT_SUPPORTED,
+#endif
 };
 
 INITCALL1(STG_REGISTER, protocol_register, &proto_quic6);
diff --git a/src/proto_tcp.c b/src/proto_tcp.c
index 2e5c36a..45ce27f 100644
--- a/src/proto_tcp.c
+++ b/src/proto_tcp.c
@@ -88,6 +88,9 @@
 	.default_iocb   = sock_accept_iocb,
 	.receivers      = LIST_HEAD_INIT(proto_tcpv4.receivers),
 	.nb_receivers   = 0,
+#ifdef SO_REUSEPORT
+	.flags          = PROTO_F_REUSEPORT_SUPPORTED,
+#endif
 };
 
 INITCALL1(STG_REGISTER, protocol_register, &proto_tcpv4);
@@ -131,6 +134,9 @@
 	.default_iocb   = sock_accept_iocb,
 	.receivers      = LIST_HEAD_INIT(proto_tcpv6.receivers),
 	.nb_receivers   = 0,
+#ifdef SO_REUSEPORT
+	.flags          = PROTO_F_REUSEPORT_SUPPORTED,
+#endif
 };
 
 INITCALL1(STG_REGISTER, protocol_register, &proto_tcpv6);
diff --git a/src/proto_udp.c b/src/proto_udp.c
index 1fd92c7..54f87d0 100644
--- a/src/proto_udp.c
+++ b/src/proto_udp.c
@@ -74,6 +74,9 @@
 	.rx_unbind      = sock_unbind,
 	.receivers      = LIST_HEAD_INIT(proto_udp4.receivers),
 	.nb_receivers   = 0,
+#ifdef SO_REUSEPORT
+	.flags          = PROTO_F_REUSEPORT_SUPPORTED,
+#endif
 };
 
 INITCALL1(STG_REGISTER, protocol_register, &proto_udp4);
@@ -108,6 +111,9 @@
 	.rx_unbind      = sock_unbind,
 	.receivers      = LIST_HEAD_INIT(proto_udp6.receivers),
 	.nb_receivers   = 0,
+#ifdef SO_REUSEPORT
+	.flags          = PROTO_F_REUSEPORT_SUPPORTED,
+#endif
 };
 
 INITCALL1(STG_REGISTER, protocol_register, &proto_udp6);
diff --git a/src/sock_inet.c b/src/sock_inet.c
index d225a9d..028ffaa 100644
--- a/src/sock_inet.c
+++ b/src/sock_inet.c
@@ -376,7 +376,7 @@
 	/* OpenBSD and Linux 3.9 support this. As it's present in old libc versions of
 	 * Linux, it might return an error that we will silently ignore.
 	 */
-	if (!ext && (global.tune.options & GTUNE_USE_REUSEPORT))
+	if (!ext && (rx->proto->flags & PROTO_F_REUSEPORT_SUPPORTED))
 		setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one));
 #endif
 
@@ -384,7 +384,7 @@
 	/* FreeBSD 12 and above use this to load-balance incoming connections.
 	 * This is limited to 256 listeners per group however.
 	 */
-	if (!ext && (global.tune.options & GTUNE_USE_REUSEPORT))
+	if (!ext && (rx->proto->flags & PROTO_F_REUSEPORT_SUPPORTED))
 		setsockopt(fd, SOL_SOCKET, SO_REUSEPORT_LB, &one, sizeof(one));
 #endif