MINOR: reload: determine the foreing binding status from the socket

Let's not look at the listener options passed by the original process
and determine from the socket itself whether it is configured for
transparent mode or not. This is cleaner and safer, and doesn't rely
on flag values that could possibly change between versions.
diff --git a/src/haproxy.c b/src/haproxy.c
index 028ebcd..5b32522 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -110,6 +110,7 @@
 #include <haproxy/peers.h>
 #include <haproxy/pool.h>
 #include <haproxy/protocol.h>
+#include <haproxy/proto_tcp.h>
 #include <haproxy/proxy.h>
 #include <haproxy/regex.h>
 #include <haproxy/sample.h>
@@ -1298,6 +1299,11 @@
 		    sizeof(xfer_sock->options));
 		curoff += sizeof(xfer_sock->options);
 
+		/* determine the foreign status directly from the socket itself */
+		xfer_sock->options &= ~LI_O_FOREIGN;
+		if (tcp_is_foreign(fd, xfer_sock->addr.ss_family))
+			xfer_sock->options |= LI_O_FOREIGN;
+
 		/* keep only the v6only flag depending on what's currently
 		 * active on the socket, and always drop the v4v6 one.
 		 */
diff --git a/src/proto_tcp.c b/src/proto_tcp.c
index 3d56cf6..2f8ec22 100644
--- a/src/proto_tcp.c
+++ b/src/proto_tcp.c
@@ -681,6 +681,65 @@
 
 }
 
+/* Returns true if the passed FD corresponds to a socket bound with LI_O_FOREIGN
+ * according to the various supported socket options. The socket's address family
+ * must be passed in <family>.
+ */
+int tcp_is_foreign(int fd, sa_family_t family)
+{
+	int val __maybe_unused;
+	socklen_t len __maybe_unused;
+
+	switch (family) {
+	case AF_INET:
+#if defined(IP_TRANSPARENT)
+		val = 0; len = sizeof(val);
+		if (getsockopt(fd, SOL_IP, IP_TRANSPARENT, &val, &len) == 0 && val)
+			return 1;
+#endif
+#if defined(IP_FREEBIND)
+		val = 0; len = sizeof(val);
+		if (getsockopt(fd, SOL_IP, IP_FREEBIND, &val, &len) == 0 && val)
+			return 1;
+#endif
+#if defined(IP_BINDANY)
+		val = 0; len = sizeof(val);
+		if (getsockopt(fd, IPPROTO_IP, IP_BINDANY, &val, &len) == 0 && val)
+			return 1;
+#endif
+#if defined(SO_BINDANY)
+		val = 0; len = sizeof(val);
+		if (getsockopt(fd, SOL_SOCKET, SO_BINDANY, &val, &len) == 0 && val)
+			return 1;
+#endif
+		break;
+
+	case AF_INET6:
+#if defined(IPV6_TRANSPARENT) && defined(SOL_IPV6)
+		val = 0; len = sizeof(val);
+		if (getsockopt(fd, SOL_IPV6, IPV6_TRANSPARENT, &val, &len) == 0 && val)
+			return 1;
+#endif
+#if defined(IP_FREEBIND)
+		val = 0; len = sizeof(val);
+		if (getsockopt(fd, SOL_IP, IP_FREEBIND, &val, &len) == 0 && val)
+			return 1;
+#endif
+#if defined(IPV6_BINDANY)
+		val = 0; len = sizeof(val);
+		if (getsockopt(fd, IPPROTO_IPV6, IPV6_BINDANY, &val, &len) == 0 && val)
+			return 1;
+#endif
+#if defined(SO_BINDANY)
+		val = 0; len = sizeof(val);
+		if (getsockopt(fd, SOL_SOCKET, SO_BINDANY, &val, &len) == 0 && val)
+			return 1;
+#endif
+		break;
+	}
+	return 0;
+}
+
 /* sets the v6only_default flag according to the OS' default settings; for
  * simplicity it's set to zero if not supported.
  */