#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);
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)
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.
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;
* 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.
}
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);