]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
REORG: sock_inet: move v6only_default from proto_tcp.c to sock_inet.c
authorWilly Tarreau <w@1wt.eu>
Fri, 28 Aug 2020 14:06:01 +0000 (16:06 +0200)
committerWilly Tarreau <w@1wt.eu>
Fri, 28 Aug 2020 16:51:36 +0000 (18:51 +0200)
The v6only_default variable is not specific to TCP but to AF_INET6, so
let's move it to the right file. It's now immediately filled on startup
during the PREPARE stage so that it doesn't have to be tested each time.
The variable's name was changed to sock_inet6_v6only_default.

include/haproxy/sock_inet.h
src/proto_tcp.c
src/sock_inet.c

index 48b23b3fd2c8c79f1d6dc84d7736c9ae7b19deed..6e3718a2d76ba7a3a0389f75eea592907a9aa5bb 100644 (file)
@@ -27,6 +27,8 @@
 
 #include <haproxy/api.h>
 
+extern int sock_inet6_v6only_default;
+
 int sock_inet4_addrcmp(const struct sockaddr_storage *a, const struct sockaddr_storage *b);
 int sock_inet6_addrcmp(const struct sockaddr_storage *a, const struct sockaddr_storage *b);
 int sock_inet_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir);
index fba60834b5528b7758c4208adb3b0912171e65ff..144f4bcfaba2c5f700f16dc426e672d3e786e3b9 100644 (file)
@@ -107,11 +107,6 @@ static THREAD_LOCAL int default_tcp_maxseg = -1;
 static THREAD_LOCAL int default_tcp6_maxseg = -1;
 #endif
 
-/* determine if the operating system uses IPV6_V6ONLY by default.
- * -1=unknown, 0=no, 1=yes.
- */
-static int v6only_default = -1;
-
 /* Binds ipv4/ipv6 address <local> to socket <fd>, unless <flags> is set, in which
  * case we try to bind <remote>. <flags> is a 2-bit field consisting of :
  *  - 0 : ignore remote address (may even be a NULL pointer)
@@ -581,32 +576,6 @@ int tcp_connect_server(struct connection *conn, int flags)
        return SF_ERR_NONE;  /* connection is OK */
 }
 
-/* sets the v6only_default flag according to the OS' default settings; for
- * simplicity it's set to zero if not supported.
- */
-static inline void tcp_test_v6only_default()
-{
-       if (v6only_default == -1) {
-#if defined(IPV6_V6ONLY)
-               int fd, val;
-               socklen_t len = sizeof(val);
-
-               v6only_default = 0;
-
-               fd = socket(AF_INET6, SOCK_STREAM, 0);
-               if (fd < 0)
-                       return;
-
-               if (getsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &val, &len) == 0 && val > 0)
-                       v6only_default = 1;
-
-               close(fd);
-#else
-               v6only_default = 0;
-#endif
-       }
-}
-
 #define LI_MANDATORY_FLAGS     (LI_O_FOREIGN | LI_O_V6ONLY)
 /* When binding the listeners, check if a socket has been sent to us by the
  * previous process that we could reuse, instead of creating a new one.
@@ -617,15 +586,13 @@ static int tcp_find_compatible_fd(struct listener *l)
        int options = l->options & (LI_MANDATORY_FLAGS | LI_O_V4V6);
        int ret = -1;
 
-       tcp_test_v6only_default();
-
        /* Prepare to match the v6only option against what we really want. Note
         * that sadly the two options are not exclusive to each other and that
         * v6only is stronger than v4v6.
         */
-       if ((options & LI_O_V6ONLY) || (v6only_default && !(options & LI_O_V4V6)))
+       if ((options & LI_O_V6ONLY) || (sock_inet6_v6only_default && !(options & LI_O_V4V6)))
                options |= LI_O_V6ONLY;
-       else if ((options & LI_O_V4V6) || !v6only_default)
+       else if ((options & LI_O_V4V6) || !sock_inet6_v6only_default)
                options &= ~LI_O_V6ONLY;
        options &= ~LI_O_V4V6;
 
index db1a8c00e4c024540ee00cb76b7fa9effa617d0d..c5b80da1c710c81c835b7c03f032555da5f26a90 100644 (file)
  * mentioned in the comment before the function definition.
  */
 
+/* determine if the operating system uses IPV6_V6ONLY by default. 0=no, 1=yes.
+ * It also remains if IPv6 is not enabled/configured.
+ */
+int sock_inet6_v6only_default = 0;
 
 /* Compares two AF_INET sockaddr addresses. Returns 0 if they match or non-zero
  * if they do not match.
@@ -165,3 +169,22 @@ int sock_inet_is_foreign(int fd, sa_family_t family)
        }
        return 0;
 }
+
+static void sock_inet_prepare()
+{
+       int fd, val;
+       socklen_t len;
+
+       fd = socket(AF_INET6, SOCK_STREAM, 0);
+       if (fd >= 0) {
+#if defined(IPV6_V6ONLY)
+               /* retrieve the OS' bindv6only value */
+               len = sizeof(val);
+               if (getsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &val, &len) == 0 && val > 0)
+                       sock_inet6_v6only_default = 1;
+#endif
+               close(fd);
+       }
+}
+
+INITCALL0(STG_PREPARE, sock_inet_prepare);