ipv6: add ip6_sock_set_v6only
authorChristoph Hellwig <hch@lst.de>
Thu, 28 May 2020 05:12:31 +0000 (07:12 +0200)
committerDavid S. Miller <davem@davemloft.net>
Thu, 28 May 2020 18:11:45 +0000 (11:11 -0700)
Add a helper to directly set the IPV6_V6ONLY sockopt from kernel space
without going through a fake uaccess.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/ipv6.h
net/ipv6/ip6_udp_tunnel.c
net/sunrpc/svcsock.c

index 39a00d3..9b91188 100644 (file)
@@ -1177,4 +1177,15 @@ int ipv6_sock_mc_join_ssm(struct sock *sk, int ifindex,
                          const struct in6_addr *addr, unsigned int mode);
 int ipv6_sock_mc_drop(struct sock *sk, int ifindex,
                      const struct in6_addr *addr);
+
+static inline int ip6_sock_set_v6only(struct sock *sk)
+{
+       if (inet_sk(sk)->inet_num)
+               return -EINVAL;
+       lock_sock(sk);
+       sk->sk_ipv6only = true;
+       release_sock(sk);
+       return 0;
+}
+
 #endif /* _NET_IPV6_H */
index 6523609..2e0ad1b 100644 (file)
@@ -25,10 +25,7 @@ int udp_sock_create6(struct net *net, struct udp_port_cfg *cfg,
                goto error;
 
        if (cfg->ipv6_v6only) {
-               int val = 1;
-
-               err = kernel_setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
-                                       (char *) &val, sizeof(val));
+               err = ip6_sock_set_v6only(sock->sk);
                if (err < 0)
                        goto error;
        }
index 7a805d1..a391892 100644 (file)
@@ -1328,7 +1328,6 @@ static struct svc_xprt *svc_create_socket(struct svc_serv *serv,
        struct sockaddr *newsin = (struct sockaddr *)&addr;
        int             newlen;
        int             family;
-       int             val;
        RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]);
 
        dprintk("svc: svc_create_socket(%s, %d, %s)\n",
@@ -1364,11 +1363,8 @@ static struct svc_xprt *svc_create_socket(struct svc_serv *serv,
         * getting requests from IPv4 remotes.  Those should
         * be shunted to a PF_INET listener via rpcbind.
         */
-       val = 1;
        if (family == PF_INET6)
-               kernel_setsockopt(sock, SOL_IPV6, IPV6_V6ONLY,
-                                       (char *)&val, sizeof(val));
-
+               ip6_sock_set_v6only(sock->sk);
        if (type == SOCK_STREAM)
                sock->sk->sk_reuse = SK_CAN_REUSE; /* allow address reuse */
        error = kernel_bind(sock, sin, len);