X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lnet%2Flnet%2Flib-socket.c;h=90cdc3e2b4dbe9bc978316d738280aacbec7582c;hp=f087710c01de03dcb46349f7358e1dcc01c0d4e4;hb=3f2844dc9333c86452c37bd7b4519729b1351371;hpb=30de2a33feae81d64cfdc7ddb76951e1fc1be916 diff --git a/lnet/lnet/lib-socket.c b/lnet/lnet/lib-socket.c index f087710..90cdc3e 100644 --- a/lnet/lnet/lib-socket.c +++ b/lnet/lnet/lib-socket.c @@ -27,7 +27,6 @@ */ /* * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. */ #define DEBUG_SUBSYSTEM S_LNET @@ -239,9 +238,50 @@ retry: #if IS_ENABLED(CONFIG_IPV6) case AF_INET6: { struct sockaddr_in6 *sin6 = (void *)&locaddr; + int val = 0; sin6->sin6_family = AF_INET6; sin6->sin6_addr = in6addr_any; + + /* Make sure we get both IPv4 and IPv6 connections. + * This is the default, but it can be overridden so we + * force it back. + */ +#ifdef HAVE_KERNEL_SETSOCKOPT + kernel_setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, + (char *) &val, sizeof(val)); +#elif defined(_LINUX_SOCKPTR_H) + /* sockptr_t was introduced around + * v5.8-rc4-1952-ga7b75c5a8c41 and allows a + * kernel address to be passed to ->setsockopt + */ + if (ipv6_only_sock(sock->sk)) { + sockptr_t optval = KERNEL_SOCKPTR(&val); + + sock->ops->setsockopt(sock, + IPPROTO_IPV6, IPV6_V6ONLY, + optval, sizeof(val)); + } +#else + /* From v5.7-rc6-2614-g5a892ff2facb when + * kernel_setsockopt() was removed until + * sockptr_t (above) there is no clean way to + * pass kernel address to setsockopt. We could + * use get_fs()/set_fs(), but in this particular + * situation there is an easier way. It depends + * on the fact that at least for these few + * kernels a NULL address to ipv6_setsockopt() + * is treated like the address of a zero. + */ + if (ipv6_only_sock(sock->sk) && !val) { + void *optval = NULL; + + sock->ops->setsockopt(sock, + IPPROTO_IPV6, IPV6_V6ONLY, + optval, sizeof(val)); + } +#endif /* HAVE_KERNEL_SETSOCKOPT */ + if (interface >= 0 && remaddr) { struct sockaddr_in6 *rem = (void *)remaddr; @@ -344,7 +384,6 @@ struct socket * lnet_sock_listen(int local_port, int backlog, struct net *ns) { struct socket *sock; - int val = 0; int rc; sock = lnet_sock_create(-1, NULL, local_port, ns); @@ -356,13 +395,6 @@ lnet_sock_listen(int local_port, int backlog, struct net *ns) return ERR_PTR(rc); } - /* Make sure we get both IPv4 and IPv6 connections. - * This is the default, but it can be overridden so - * we force it back. - */ - kernel_setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, - (char *) &val, sizeof(val)); - rc = kernel_listen(sock, backlog); if (rc == 0) return sock;