b24413180f560 (Greg Kroah-Hartman 2017-11-01 15:07:57 +0100 1) // SPDX-License-Identifier: GPL-2.0
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 3) * linux/fs/nfs/callback.c
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 4) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 5) * Copyright (C) 2004 Trond Myklebust
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 6) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 7) * NFSv4 callback handling
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 8) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 9)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 10) #include <linux/completion.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 11) #include <linux/ip.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 12) #include <linux/module.h>
3f07c0144132e (Ingo Molnar 2017-02-08 18:51:30 +0100 13) #include <linux/sched/signal.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 14) #include <linux/sunrpc/svc.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 15) #include <linux/sunrpc/svcsock.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 16) #include <linux/nfs_fs.h>
758201e2c94b7 (Trond Myklebust 2012-10-01 16:33:18 -0700 17) #include <linux/errno.h>
353ab6e97b8f2 (Ingo Molnar 2006-03-26 01:37:12 -0800 18) #include <linux/mutex.h>
831441862956f (Rafael J. Wysocki 2007-07-17 04:03:35 -0700 19) #include <linux/freezer.h>
a277e33cbe3fd (Jeff Layton 2008-02-20 08:55:30 -0500 20) #include <linux/kthread.h>
945b34a7725a5 (Olga Kornievskaia 2008-12-23 16:18:34 -0500 21) #include <linux/sunrpc/svcauth_gss.h>
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 22) #include <linux/sunrpc/bc_xprt.h>
14c850212ed8f (Arnaldo Carvalho de Melo 2005-12-27 02:43:12 -0200 23)
14c850212ed8f (Arnaldo Carvalho de Melo 2005-12-27 02:43:12 -0200 24) #include <net/inet_sock.h>
14c850212ed8f (Arnaldo Carvalho de Melo 2005-12-27 02:43:12 -0200 25)
4ce79717ce32a (Trond Myklebust 2005-06-22 17:16:21 +0000 26) #include "nfs4_fs.h"
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 27) #include "callback.h"
24c8dbbb5f777 (David Howells 2006-08-22 20:06:10 -0400 28) #include "internal.h"
bbe0a3aa4e227 (Stanislav Kinsbursky 2012-08-20 18:00:36 +0400 29) #include "netns.h"
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 30)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 31) #define NFSDBG_FACILITY NFSDBG_CALLBACK
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 32)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 33) struct nfs_callback_data {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 34) unsigned int users;
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 35) struct svc_serv *serv;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 36) };
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 37)
e82dc22dac652 (Andy Adamson 2009-04-01 09:23:14 -0400 38) static struct nfs_callback_data nfs_callback_info[NFS4_MAX_MINOR_VERSION + 1];
353ab6e97b8f2 (Ingo Molnar 2006-03-26 01:37:12 -0800 39) static DEFINE_MUTEX(nfs_callback_mutex);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 40) static struct svc_program nfs4_callback_program;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 41)
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 42) static int nfs4_callback_up_net(struct svc_serv *serv, struct net *net)
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 43) {
4df493a260d4c (Trond Myklebust 2019-04-09 12:13:37 -0400 44) const struct cred *cred = current_cred();
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 45) int ret;
bbe0a3aa4e227 (Stanislav Kinsbursky 2012-08-20 18:00:36 +0400 46) struct nfs_net *nn = net_generic(net, nfs_net_id);
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 47)
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 48) ret = svc_create_xprt(serv, "tcp", net, PF_INET,
4df493a260d4c (Trond Myklebust 2019-04-09 12:13:37 -0400 49) nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS,
4df493a260d4c (Trond Myklebust 2019-04-09 12:13:37 -0400 50) cred);
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 51) if (ret <= 0)
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 52) goto out_err;
bbe0a3aa4e227 (Stanislav Kinsbursky 2012-08-20 18:00:36 +0400 53) nn->nfs_callback_tcpport = ret;
e4949e4b3d5e0 (Vasily Averin 2017-11-08 08:56:55 +0300 54) dprintk("NFS: Callback listener port = %u (af %u, net %x)\n",
e4949e4b3d5e0 (Vasily Averin 2017-11-08 08:56:55 +0300 55) nn->nfs_callback_tcpport, PF_INET, net->ns.inum);
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 56)
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 57) ret = svc_create_xprt(serv, "tcp", net, PF_INET6,
4df493a260d4c (Trond Myklebust 2019-04-09 12:13:37 -0400 58) nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS,
4df493a260d4c (Trond Myklebust 2019-04-09 12:13:37 -0400 59) cred);
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 60) if (ret > 0) {
29dcc16a8e293 (Stanislav Kinsbursky 2012-08-20 18:00:41 +0400 61) nn->nfs_callback_tcpport6 = ret;
91bd2ffa90301 (Vasily Averin 2018-12-24 14:46:21 +0300 62) dprintk("NFS: Callback listener port = %u (af %u, net %x)\n",
e4949e4b3d5e0 (Vasily Averin 2017-11-08 08:56:55 +0300 63) nn->nfs_callback_tcpport6, PF_INET6, net->ns.inum);
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 64) } else if (ret != -EAFNOSUPPORT)
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 65) goto out_err;
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 66) return 0;
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 67)
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 68) out_err:
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 69) return (ret) ? ret : -ENOMEM;
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 70) }
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 71)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 72) /*
e82dc22dac652 (Andy Adamson 2009-04-01 09:23:14 -0400 73) * This is the NFSv4 callback kernel thread.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 74) */
a277e33cbe3fd (Jeff Layton 2008-02-20 08:55:30 -0500 75) static int
7146851376861 (Benny Halevy 2009-04-01 09:22:56 -0400 76) nfs4_callback_svc(void *vrqstp)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 77) {
5b444cc9a4c97 (J. Bruce Fields 2012-08-17 21:47:53 -0400 78) int err;
a277e33cbe3fd (Jeff Layton 2008-02-20 08:55:30 -0500 79) struct svc_rqst *rqstp = vrqstp;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 80)
831441862956f (Rafael J. Wysocki 2007-07-17 04:03:35 -0700 81) set_freezable();
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 82)
ed6473ddc704a (Trond Myklebust 2017-04-26 11:55:27 -0400 83) while (!kthread_freezable_should_stop(NULL)) {
ed6473ddc704a (Trond Myklebust 2017-04-26 11:55:27 -0400 84)
ed6473ddc704a (Trond Myklebust 2017-04-26 11:55:27 -0400 85) if (signal_pending(current))
ed6473ddc704a (Trond Myklebust 2017-04-26 11:55:27 -0400 86) flush_signals(current);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 87) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 88) * Listen for a request on the socket
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 89) */
6fb2b47fa16c8 (NeilBrown 2006-10-02 02:17:50 -0700 90) err = svc_recv(rqstp, MAX_SCHEDULE_TIMEOUT);
5b444cc9a4c97 (J. Bruce Fields 2012-08-17 21:47:53 -0400 91) if (err == -EAGAIN || err == -EINTR)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 92) continue;
6fb2b47fa16c8 (NeilBrown 2006-10-02 02:17:50 -0700 93) svc_process(rqstp);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 94) }
ed6473ddc704a (Trond Myklebust 2017-04-26 11:55:27 -0400 95) svc_exit_thread(rqstp);
ed6473ddc704a (Trond Myklebust 2017-04-26 11:55:27 -0400 96) module_put_and_exit(0);
a277e33cbe3fd (Jeff Layton 2008-02-20 08:55:30 -0500 97) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 98) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 99)
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 100) #if defined(CONFIG_NFS_V4_1)
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 101) /*
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 102) * The callback service for NFSv4.1 callbacks
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 103) */
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 104) static int
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 105) nfs41_callback_svc(void *vrqstp)
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 106) {
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 107) struct svc_rqst *rqstp = vrqstp;
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 108) struct svc_serv *serv = rqstp->rq_server;
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 109) struct rpc_rqst *req;
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 110) int error;
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 111) DEFINE_WAIT(wq);
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 112)
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 113) set_freezable();
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 114)
ed6473ddc704a (Trond Myklebust 2017-04-26 11:55:27 -0400 115) while (!kthread_freezable_should_stop(NULL)) {
ed6473ddc704a (Trond Myklebust 2017-04-26 11:55:27 -0400 116)
ed6473ddc704a (Trond Myklebust 2017-04-26 11:55:27 -0400 117) if (signal_pending(current))
ed6473ddc704a (Trond Myklebust 2017-04-26 11:55:27 -0400 118) flush_signals(current);
25d280aad82e5 (Jeff Layton 2013-03-25 07:59:57 -0400 119)
5d05e54af3cdb (Jeff Layton 2015-03-20 15:15:14 -0400 120) prepare_to_wait(&serv->sv_cb_waitq, &wq, TASK_INTERRUPTIBLE);
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 121) spin_lock_bh(&serv->sv_cb_lock);
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 122) if (!list_empty(&serv->sv_cb_list)) {
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 123) req = list_first_entry(&serv->sv_cb_list,
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 124) struct rpc_rqst, rq_bc_list);
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 125) list_del(&req->rq_bc_list);
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 126) spin_unlock_bh(&serv->sv_cb_lock);
6ffa30d3f734d (Jeff Layton 2015-01-14 13:08:57 -0500 127) finish_wait(&serv->sv_cb_waitq, &wq);
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 128) dprintk("Invoking bc_svc_process()\n");
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 129) error = bc_svc_process(serv, req, rqstp);
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 130) dprintk("bc_svc_process() returned w/ error code= %d\n",
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 131) error);
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 132) } else {
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 133) spin_unlock_bh(&serv->sv_cb_lock);
ed6473ddc704a (Trond Myklebust 2017-04-26 11:55:27 -0400 134) if (!kthread_should_stop())
ed6473ddc704a (Trond Myklebust 2017-04-26 11:55:27 -0400 135) schedule();
6ffa30d3f734d (Jeff Layton 2015-01-14 13:08:57 -0500 136) finish_wait(&serv->sv_cb_waitq, &wq);
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 137) }
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 138) }
ed6473ddc704a (Trond Myklebust 2017-04-26 11:55:27 -0400 139) svc_exit_thread(rqstp);
ed6473ddc704a (Trond Myklebust 2017-04-26 11:55:27 -0400 140) module_put_and_exit(0);
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 141) return 0;
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 142) }
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 143)
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 144) static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt,
691c457ae635a (Stanislav Kinsbursky 2012-08-20 18:00:21 +0400 145) struct svc_serv *serv)
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 146) {
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 147) if (minorversion)
691c457ae635a (Stanislav Kinsbursky 2012-08-20 18:00:21 +0400 148) /*
691c457ae635a (Stanislav Kinsbursky 2012-08-20 18:00:21 +0400 149) * Save the svc_serv in the transport so that it can
691c457ae635a (Stanislav Kinsbursky 2012-08-20 18:00:21 +0400 150) * be referenced when the session backchannel is initialized
691c457ae635a (Stanislav Kinsbursky 2012-08-20 18:00:21 +0400 151) */
691c457ae635a (Stanislav Kinsbursky 2012-08-20 18:00:21 +0400 152) xprt->bc_serv = serv;
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 153) }
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 154) #else
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 155) static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt,
691c457ae635a (Stanislav Kinsbursky 2012-08-20 18:00:21 +0400 156) struct svc_serv *serv)
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 157) {
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 158) }
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 159) #endif /* CONFIG_NFS_V4_1 */
a43cde94feded (Ricardo Labiaga 2009-04-01 09:23:08 -0400 160)
8e2461444319b (Stanislav Kinsbursky 2012-08-20 18:00:26 +0400 161) static int nfs_callback_start_svc(int minorversion, struct rpc_xprt *xprt,
8e2461444319b (Stanislav Kinsbursky 2012-08-20 18:00:26 +0400 162) struct svc_serv *serv)
8e2461444319b (Stanislav Kinsbursky 2012-08-20 18:00:26 +0400 163) {
5405fc44c3377 (Trond Myklebust 2016-08-29 20:03:52 -0400 164) int nrservs = nfs_callback_nr_threads;
8e2461444319b (Stanislav Kinsbursky 2012-08-20 18:00:26 +0400 165) int ret;
8e2461444319b (Stanislav Kinsbursky 2012-08-20 18:00:26 +0400 166)
8e2461444319b (Stanislav Kinsbursky 2012-08-20 18:00:26 +0400 167) nfs_callback_bc_serv(minorversion, xprt, serv);
8e2461444319b (Stanislav Kinsbursky 2012-08-20 18:00:26 +0400 168)
5405fc44c3377 (Trond Myklebust 2016-08-29 20:03:52 -0400 169) if (nrservs < NFS4_MIN_NR_CALLBACK_THREADS)
5405fc44c3377 (Trond Myklebust 2016-08-29 20:03:52 -0400 170) nrservs = NFS4_MIN_NR_CALLBACK_THREADS;
5405fc44c3377 (Trond Myklebust 2016-08-29 20:03:52 -0400 171)
bb6aeba736ba9 (Trond Myklebust 2016-08-29 20:03:51 -0400 172) if (serv->sv_nrthreads-1 == nrservs)
23c20ecd44750 (Stanislav Kinsbursky 2012-08-20 18:00:31 +0400 173) return 0;
23c20ecd44750 (Stanislav Kinsbursky 2012-08-20 18:00:31 +0400 174)
bb6aeba736ba9 (Trond Myklebust 2016-08-29 20:03:51 -0400 175) ret = serv->sv_ops->svo_setup(serv, NULL, nrservs);
bb6aeba736ba9 (Trond Myklebust 2016-08-29 20:03:51 -0400 176) if (ret) {
bb6aeba736ba9 (Trond Myklebust 2016-08-29 20:03:51 -0400 177) serv->sv_ops->svo_setup(serv, NULL, 0);
e9b7e91745fa9 (Trond Myklebust 2012-10-16 12:30:44 -0400 178) return ret;
8e2461444319b (Stanislav Kinsbursky 2012-08-20 18:00:26 +0400 179) }
8e2461444319b (Stanislav Kinsbursky 2012-08-20 18:00:26 +0400 180) dprintk("nfs_callback_up: service started\n");
8e2461444319b (Stanislav Kinsbursky 2012-08-20 18:00:26 +0400 181) return 0;
8e2461444319b (Stanislav Kinsbursky 2012-08-20 18:00:26 +0400 182) }
8e2461444319b (Stanislav Kinsbursky 2012-08-20 18:00:26 +0400 183)
b3d19c51723be (Stanislav Kinsbursky 2012-08-20 18:00:46 +0400 184) static void nfs_callback_down_net(u32 minorversion, struct svc_serv *serv, struct net *net)
b3d19c51723be (Stanislav Kinsbursky 2012-08-20 18:00:46 +0400 185) {
b3d19c51723be (Stanislav Kinsbursky 2012-08-20 18:00:46 +0400 186) struct nfs_net *nn = net_generic(net, nfs_net_id);
b3d19c51723be (Stanislav Kinsbursky 2012-08-20 18:00:46 +0400 187)
b3d19c51723be (Stanislav Kinsbursky 2012-08-20 18:00:46 +0400 188) if (--nn->cb_users[minorversion])
b3d19c51723be (Stanislav Kinsbursky 2012-08-20 18:00:46 +0400 189) return;
b3d19c51723be (Stanislav Kinsbursky 2012-08-20 18:00:46 +0400 190)
e4949e4b3d5e0 (Vasily Averin 2017-11-08 08:56:55 +0300 191) dprintk("NFS: destroy per-net callback data; net=%x\n", net->ns.inum);
b3d19c51723be (Stanislav Kinsbursky 2012-08-20 18:00:46 +0400 192) svc_shutdown_net(serv, net);
b3d19c51723be (Stanislav Kinsbursky 2012-08-20 18:00:46 +0400 193) }
b3d19c51723be (Stanislav Kinsbursky 2012-08-20 18:00:46 +0400 194)
76566773a1f1c (Chuck Lever 2015-10-24 17:28:32 -0400 195) static int nfs_callback_up_net(int minorversion, struct svc_serv *serv,
76566773a1f1c (Chuck Lever 2015-10-24 17:28:32 -0400 196) struct net *net, struct rpc_xprt *xprt)
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 197) {
b3d19c51723be (Stanislav Kinsbursky 2012-08-20 18:00:46 +0400 198) struct nfs_net *nn = net_generic(net, nfs_net_id);
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 199) int ret;
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 200)
b3d19c51723be (Stanislav Kinsbursky 2012-08-20 18:00:46 +0400 201) if (nn->cb_users[minorversion]++)
b3d19c51723be (Stanislav Kinsbursky 2012-08-20 18:00:46 +0400 202) return 0;
b3d19c51723be (Stanislav Kinsbursky 2012-08-20 18:00:46 +0400 203)
e4949e4b3d5e0 (Vasily Averin 2017-11-08 08:56:55 +0300 204) dprintk("NFS: create per-net callback data; net=%x\n", net->ns.inum);
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 205)
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 206) ret = svc_bind(serv, net);
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 207) if (ret < 0) {
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 208) printk(KERN_WARNING "NFS: bind callback service failed\n");
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 209) goto err_bind;
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 210) }
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 211)
a289ce5311f40 (Vasily Averin 2018-12-24 14:45:04 +0300 212) ret = 0;
d55b352b01bc7 (Arnd Bergmann 2016-11-22 21:50:52 +0100 213) if (!IS_ENABLED(CONFIG_NFS_V4_1) || minorversion == 0)
76566773a1f1c (Chuck Lever 2015-10-24 17:28:32 -0400 214) ret = nfs4_callback_up_net(serv, net);
a289ce5311f40 (Vasily Averin 2018-12-24 14:45:04 +0300 215) else if (xprt->ops->bc_setup)
0ad30ff67bd3e (Vasily Averin 2018-12-29 16:38:51 +0300 216) set_bc_enabled(serv);
a289ce5311f40 (Vasily Averin 2018-12-24 14:45:04 +0300 217) else
a289ce5311f40 (Vasily Averin 2018-12-24 14:45:04 +0300 218) ret = -EPROTONOSUPPORT;
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 219)
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 220) if (ret < 0) {
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 221) printk(KERN_ERR "NFS: callback service start failed\n");
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 222) goto err_socks;
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 223) }
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 224) return 0;
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 225)
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 226) err_socks:
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 227) svc_rpcb_cleanup(serv, net);
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 228) err_bind:
98b0f80c23962 (Trond Myklebust 2016-08-29 11:15:36 -0400 229) nn->cb_users[minorversion]--;
23c20ecd44750 (Stanislav Kinsbursky 2012-08-20 18:00:31 +0400 230) dprintk("NFS: Couldn't create callback socket: err = %d; "
e4949e4b3d5e0 (Vasily Averin 2017-11-08 08:56:55 +0300 231) "net = %x\n", ret, net->ns.inum);
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 232) return ret;
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 233) }
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 234)
afea5657c20b1 (Chuck Lever 2017-08-01 12:00:06 -0400 235) static const struct svc_serv_ops nfs40_cb_sv_ops = {
f4b52bb084264 (Trond Myklebust 2016-08-29 20:03:48 -0400 236) .svo_function = nfs4_callback_svc,
b9e13cdfac70e (Jeff Layton 2015-06-08 12:06:51 -0700 237) .svo_enqueue_xprt = svc_xprt_do_enqueue,
ed6473ddc704a (Trond Myklebust 2017-04-26 11:55:27 -0400 238) .svo_setup = svc_set_num_threads_sync,
f4b52bb084264 (Trond Myklebust 2016-08-29 20:03:48 -0400 239) .svo_module = THIS_MODULE,
f4b52bb084264 (Trond Myklebust 2016-08-29 20:03:48 -0400 240) };
f4b52bb084264 (Trond Myklebust 2016-08-29 20:03:48 -0400 241) #if defined(CONFIG_NFS_V4_1)
afea5657c20b1 (Chuck Lever 2017-08-01 12:00:06 -0400 242) static const struct svc_serv_ops nfs41_cb_sv_ops = {
f4b52bb084264 (Trond Myklebust 2016-08-29 20:03:48 -0400 243) .svo_function = nfs41_callback_svc,
f4b52bb084264 (Trond Myklebust 2016-08-29 20:03:48 -0400 244) .svo_enqueue_xprt = svc_xprt_do_enqueue,
ed6473ddc704a (Trond Myklebust 2017-04-26 11:55:27 -0400 245) .svo_setup = svc_set_num_threads_sync,
f4b52bb084264 (Trond Myklebust 2016-08-29 20:03:48 -0400 246) .svo_module = THIS_MODULE,
ea126e7435345 (Jeff Layton 2015-06-08 12:03:32 -0700 247) };
ea126e7435345 (Jeff Layton 2015-06-08 12:03:32 -0700 248)
afea5657c20b1 (Chuck Lever 2017-08-01 12:00:06 -0400 249) static const struct svc_serv_ops *nfs4_cb_sv_ops[] = {
f4b52bb084264 (Trond Myklebust 2016-08-29 20:03:48 -0400 250) [0] = &nfs40_cb_sv_ops,
f4b52bb084264 (Trond Myklebust 2016-08-29 20:03:48 -0400 251) [1] = &nfs41_cb_sv_ops,
f4b52bb084264 (Trond Myklebust 2016-08-29 20:03:48 -0400 252) };
f4b52bb084264 (Trond Myklebust 2016-08-29 20:03:48 -0400 253) #else
afea5657c20b1 (Chuck Lever 2017-08-01 12:00:06 -0400 254) static const struct svc_serv_ops *nfs4_cb_sv_ops[] = {
f4b52bb084264 (Trond Myklebust 2016-08-29 20:03:48 -0400 255) [0] = &nfs40_cb_sv_ops,
f4b52bb084264 (Trond Myklebust 2016-08-29 20:03:48 -0400 256) [1] = NULL,
f4b52bb084264 (Trond Myklebust 2016-08-29 20:03:48 -0400 257) };
f4b52bb084264 (Trond Myklebust 2016-08-29 20:03:48 -0400 258) #endif
f4b52bb084264 (Trond Myklebust 2016-08-29 20:03:48 -0400 259)
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 260) static struct svc_serv *nfs_callback_create_svc(int minorversion)
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 261) {
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 262) struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion];
afea5657c20b1 (Chuck Lever 2017-08-01 12:00:06 -0400 263) const struct svc_serv_ops *sv_ops;
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 264) struct svc_serv *serv;
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 265)
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 266) /*
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 267) * Check whether we're already up and running.
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 268) */
3b01c11ee8bfa (Trond Myklebust 2016-08-29 20:03:50 -0400 269) if (cb_info->serv) {
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 270) /*
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 271) * Note: increase service usage, because later in case of error
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 272) * svc_destroy() will be called.
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 273) */
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 274) svc_get(cb_info->serv);
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 275) return cb_info->serv;
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 276) }
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 277)
f4b52bb084264 (Trond Myklebust 2016-08-29 20:03:48 -0400 278) switch (minorversion) {
f4b52bb084264 (Trond Myklebust 2016-08-29 20:03:48 -0400 279) case 0:
f4b52bb084264 (Trond Myklebust 2016-08-29 20:03:48 -0400 280) sv_ops = nfs4_cb_sv_ops[0];
f4b52bb084264 (Trond Myklebust 2016-08-29 20:03:48 -0400 281) break;
f4b52bb084264 (Trond Myklebust 2016-08-29 20:03:48 -0400 282) default:
f4b52bb084264 (Trond Myklebust 2016-08-29 20:03:48 -0400 283) sv_ops = nfs4_cb_sv_ops[1];
f4b52bb084264 (Trond Myklebust 2016-08-29 20:03:48 -0400 284) }
f4b52bb084264 (Trond Myklebust 2016-08-29 20:03:48 -0400 285)
f4b52bb084264 (Trond Myklebust 2016-08-29 20:03:48 -0400 286) if (sv_ops == NULL)
f4b52bb084264 (Trond Myklebust 2016-08-29 20:03:48 -0400 287) return ERR_PTR(-ENOTSUPP);
f4b52bb084264 (Trond Myklebust 2016-08-29 20:03:48 -0400 288)
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 289) /*
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 290) * Sanity check: if there's no task,
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 291) * we should be the first user ...
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 292) */
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 293) if (cb_info->users)
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 294) printk(KERN_WARNING "nfs_callback_create_svc: no kthread, %d users??\n",
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 295) cb_info->users);
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 296)
df807fffaabde (Kinglong Mee 2017-04-27 11:13:38 +0800 297) serv = svc_create_pooled(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, sv_ops);
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 298) if (!serv) {
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 299) printk(KERN_ERR "nfs_callback_create_svc: create service failed\n");
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 300) return ERR_PTR(-ENOMEM);
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 301) }
3b01c11ee8bfa (Trond Myklebust 2016-08-29 20:03:50 -0400 302) cb_info->serv = serv;
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 303) /* As there is only one thread we need to over-ride the
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 304) * default maximum of 80 connections
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 305) */
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 306) serv->sv_maxconn = 1024;
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 307) dprintk("nfs_callback_create_svc: service created\n");
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 308) return serv;
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 309) }
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 310)
7146851376861 (Benny Halevy 2009-04-01 09:22:56 -0400 311) /*
7146851376861 (Benny Halevy 2009-04-01 09:22:56 -0400 312) * Bring up the callback thread if it is not already up.
7146851376861 (Benny Halevy 2009-04-01 09:22:56 -0400 313) */
7146851376861 (Benny Halevy 2009-04-01 09:22:56 -0400 314) int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt)
7146851376861 (Benny Halevy 2009-04-01 09:22:56 -0400 315) {
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 316) struct svc_serv *serv;
e82dc22dac652 (Andy Adamson 2009-04-01 09:23:14 -0400 317) struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion];
23c20ecd44750 (Stanislav Kinsbursky 2012-08-20 18:00:31 +0400 318) int ret;
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 319) struct net *net = xprt->xprt_net;
7146851376861 (Benny Halevy 2009-04-01 09:22:56 -0400 320)
7146851376861 (Benny Halevy 2009-04-01 09:22:56 -0400 321) mutex_lock(&nfs_callback_mutex);
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 322)
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 323) serv = nfs_callback_create_svc(minorversion);
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 324) if (IS_ERR(serv)) {
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 325) ret = PTR_ERR(serv);
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 326) goto err_create;
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 327) }
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 328)
76566773a1f1c (Chuck Lever 2015-10-24 17:28:32 -0400 329) ret = nfs_callback_up_net(minorversion, serv, net, xprt);
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 330) if (ret < 0)
c946556b8749b (Stanislav Kinsbursky 2012-08-20 18:00:16 +0400 331) goto err_net;
9793f7c88937e (Stanislav Kinsbursky 2012-05-02 16:08:38 +0400 332)
8e2461444319b (Stanislav Kinsbursky 2012-08-20 18:00:26 +0400 333) ret = nfs_callback_start_svc(minorversion, xprt, serv);
8e2461444319b (Stanislav Kinsbursky 2012-08-20 18:00:26 +0400 334) if (ret < 0)
8e2461444319b (Stanislav Kinsbursky 2012-08-20 18:00:26 +0400 335) goto err_start;
a277e33cbe3fd (Jeff Layton 2008-02-20 08:55:30 -0500 336)
23c20ecd44750 (Stanislav Kinsbursky 2012-08-20 18:00:31 +0400 337) cb_info->users++;
8e60029f40378 (Jeff Layton 2008-02-11 10:00:20 -0500 338) /*
8e60029f40378 (Jeff Layton 2008-02-11 10:00:20 -0500 339) * svc_create creates the svc_serv with sv_nrthreads == 1, and then
a277e33cbe3fd (Jeff Layton 2008-02-20 08:55:30 -0500 340) * svc_prepare_thread increments that. So we need to call svc_destroy
8e60029f40378 (Jeff Layton 2008-02-11 10:00:20 -0500 341) * on both success and failure so that the refcount is 1 when the
8e60029f40378 (Jeff Layton 2008-02-11 10:00:20 -0500 342) * thread exits.
8e60029f40378 (Jeff Layton 2008-02-11 10:00:20 -0500 343) */
23c20ecd44750 (Stanislav Kinsbursky 2012-08-20 18:00:31 +0400 344) err_net:
3b01c11ee8bfa (Trond Myklebust 2016-08-29 20:03:50 -0400 345) if (!cb_info->users)
3b01c11ee8bfa (Trond Myklebust 2016-08-29 20:03:50 -0400 346) cb_info->serv = NULL;
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 347) svc_destroy(serv);
dd018428dce08 (Stanislav Kinsbursky 2012-08-20 18:00:11 +0400 348) err_create:
353ab6e97b8f2 (Ingo Molnar 2006-03-26 01:37:12 -0800 349) mutex_unlock(&nfs_callback_mutex);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 350) return ret;
8e2461444319b (Stanislav Kinsbursky 2012-08-20 18:00:26 +0400 351)
8e2461444319b (Stanislav Kinsbursky 2012-08-20 18:00:26 +0400 352) err_start:
b3d19c51723be (Stanislav Kinsbursky 2012-08-20 18:00:46 +0400 353) nfs_callback_down_net(minorversion, serv, net);
23c20ecd44750 (Stanislav Kinsbursky 2012-08-20 18:00:31 +0400 354) dprintk("NFS: Couldn't create server thread; err = %d\n", ret);
23c20ecd44750 (Stanislav Kinsbursky 2012-08-20 18:00:31 +0400 355) goto err_net;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 356) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 357)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 358) /*
5afc597c5f0bd (Jeff Layton 2008-06-11 10:03:11 -0400 359) * Kill the callback thread if it's no longer being used.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 360) */
c8ceb4124b53a (Stanislav Kinsbursky 2012-08-20 18:00:06 +0400 361) void nfs_callback_down(int minorversion, struct net *net)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 362) {
e82dc22dac652 (Andy Adamson 2009-04-01 09:23:14 -0400 363) struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion];
bb6aeba736ba9 (Trond Myklebust 2016-08-29 20:03:51 -0400 364) struct svc_serv *serv;
e82dc22dac652 (Andy Adamson 2009-04-01 09:23:14 -0400 365)
353ab6e97b8f2 (Ingo Molnar 2006-03-26 01:37:12 -0800 366) mutex_lock(&nfs_callback_mutex);
bb6aeba736ba9 (Trond Myklebust 2016-08-29 20:03:51 -0400 367) serv = cb_info->serv;
bb6aeba736ba9 (Trond Myklebust 2016-08-29 20:03:51 -0400 368) nfs_callback_down_net(minorversion, serv, net);
e82dc22dac652 (Andy Adamson 2009-04-01 09:23:14 -0400 369) cb_info->users--;
3b01c11ee8bfa (Trond Myklebust 2016-08-29 20:03:50 -0400 370) if (cb_info->users == 0) {
bb6aeba736ba9 (Trond Myklebust 2016-08-29 20:03:51 -0400 371) svc_get(serv);
bb6aeba736ba9 (Trond Myklebust 2016-08-29 20:03:51 -0400 372) serv->sv_ops->svo_setup(serv, NULL, 0);
bb6aeba736ba9 (Trond Myklebust 2016-08-29 20:03:51 -0400 373) svc_destroy(serv);
1dc42e04b7577 (Stanislav Kinsbursky 2012-08-20 18:00:51 +0400 374) dprintk("nfs_callback_down: service destroyed\n");
e82dc22dac652 (Andy Adamson 2009-04-01 09:23:14 -0400 375) cb_info->serv = NULL;
5afc597c5f0bd (Jeff Layton 2008-06-11 10:03:11 -0400 376) }
353ab6e97b8f2 (Ingo Molnar 2006-03-26 01:37:12 -0800 377) mutex_unlock(&nfs_callback_mutex);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 378) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 379)
778be232a207e (Andy Adamson 2011-01-25 15:38:01 +0000 380) /* Boolean check of RPC_AUTH_GSS principal */
778be232a207e (Andy Adamson 2011-01-25 15:38:01 +0000 381) int
778be232a207e (Andy Adamson 2011-01-25 15:38:01 +0000 382) check_gss_callback_principal(struct nfs_client *clp, struct svc_rqst *rqstp)
945b34a7725a5 (Olga Kornievskaia 2008-12-23 16:18:34 -0500 383) {
03a4e1f6ddf25 (J. Bruce Fields 2012-05-14 19:55:22 -0400 384) char *p = rqstp->rq_cred.cr_principal;
945b34a7725a5 (Olga Kornievskaia 2008-12-23 16:18:34 -0500 385)
778be232a207e (Andy Adamson 2011-01-25 15:38:01 +0000 386) if (rqstp->rq_authop->flavour != RPC_AUTH_GSS)
778be232a207e (Andy Adamson 2011-01-25 15:38:01 +0000 387) return 1;
778be232a207e (Andy Adamson 2011-01-25 15:38:01 +0000 388)
ece0de633c4d9 (Andy Adamson 2011-01-06 02:04:33 +0000 389) /* No RPC_AUTH_GSS on NFSv4.1 back channel yet */
ece0de633c4d9 (Andy Adamson 2011-01-06 02:04:33 +0000 390) if (clp->cl_minorversion != 0)
778be232a207e (Andy Adamson 2011-01-25 15:38:01 +0000 391) return 0;
945b34a7725a5 (Olga Kornievskaia 2008-12-23 16:18:34 -0500 392) /*
945b34a7725a5 (Olga Kornievskaia 2008-12-23 16:18:34 -0500 393) * It might just be a normal user principal, in which case
945b34a7725a5 (Olga Kornievskaia 2008-12-23 16:18:34 -0500 394) * userspace won't bother to tell us the name at all.
945b34a7725a5 (Olga Kornievskaia 2008-12-23 16:18:34 -0500 395) */
945b34a7725a5 (Olga Kornievskaia 2008-12-23 16:18:34 -0500 396) if (p == NULL)
778be232a207e (Andy Adamson 2011-01-25 15:38:01 +0000 397) return 0;
945b34a7725a5 (Olga Kornievskaia 2008-12-23 16:18:34 -0500 398)
f11b2a1cfbf5d (Jeff Layton 2014-06-21 20:52:17 -0400 399) /*
f11b2a1cfbf5d (Jeff Layton 2014-06-21 20:52:17 -0400 400) * Did we get the acceptor from userland during the SETCLIENID
f11b2a1cfbf5d (Jeff Layton 2014-06-21 20:52:17 -0400 401) * negotiation?
f11b2a1cfbf5d (Jeff Layton 2014-06-21 20:52:17 -0400 402) */
f11b2a1cfbf5d (Jeff Layton 2014-06-21 20:52:17 -0400 403) if (clp->cl_acceptor)
f11b2a1cfbf5d (Jeff Layton 2014-06-21 20:52:17 -0400 404) return !strcmp(p, clp->cl_acceptor);
f11b2a1cfbf5d (Jeff Layton 2014-06-21 20:52:17 -0400 405)
f11b2a1cfbf5d (Jeff Layton 2014-06-21 20:52:17 -0400 406) /*
f11b2a1cfbf5d (Jeff Layton 2014-06-21 20:52:17 -0400 407) * Otherwise try to verify it using the cl_hostname. Note that this
f11b2a1cfbf5d (Jeff Layton 2014-06-21 20:52:17 -0400 408) * doesn't work if a non-canonical hostname was used in the devname.
f11b2a1cfbf5d (Jeff Layton 2014-06-21 20:52:17 -0400 409) */
f11b2a1cfbf5d (Jeff Layton 2014-06-21 20:52:17 -0400 410)
945b34a7725a5 (Olga Kornievskaia 2008-12-23 16:18:34 -0500 411) /* Expect a GSS_C_NT_HOSTBASED_NAME like "nfs@serverhostname" */
945b34a7725a5 (Olga Kornievskaia 2008-12-23 16:18:34 -0500 412)
945b34a7725a5 (Olga Kornievskaia 2008-12-23 16:18:34 -0500 413) if (memcmp(p, "nfs@", 4) != 0)
778be232a207e (Andy Adamson 2011-01-25 15:38:01 +0000 414) return 0;
945b34a7725a5 (Olga Kornievskaia 2008-12-23 16:18:34 -0500 415) p += 4;
4e0038b6b246e (Trond Myklebust 2012-03-01 17:01:05 -0500 416) if (strcmp(p, clp->cl_hostname) != 0)
778be232a207e (Andy Adamson 2011-01-25 15:38:01 +0000 417) return 0;
778be232a207e (Andy Adamson 2011-01-25 15:38:01 +0000 418) return 1;
945b34a7725a5 (Olga Kornievskaia 2008-12-23 16:18:34 -0500 419) }
945b34a7725a5 (Olga Kornievskaia 2008-12-23 16:18:34 -0500 420)
778be232a207e (Andy Adamson 2011-01-25 15:38:01 +0000 421) /*
778be232a207e (Andy Adamson 2011-01-25 15:38:01 +0000 422) * pg_authenticate method for nfsv4 callback threads.
778be232a207e (Andy Adamson 2011-01-25 15:38:01 +0000 423) *
778be232a207e (Andy Adamson 2011-01-25 15:38:01 +0000 424) * The authflavor has been negotiated, so an incorrect flavor is a server
6f02dc88be1d5 (Jeff Layton 2015-06-04 18:40:13 -0400 425) * bug. Deny packets with incorrect authflavor.
778be232a207e (Andy Adamson 2011-01-25 15:38:01 +0000 426) *
778be232a207e (Andy Adamson 2011-01-25 15:38:01 +0000 427) * All other checking done after NFS decoding where the nfs_client can be
778be232a207e (Andy Adamson 2011-01-25 15:38:01 +0000 428) * found in nfs4_callback_compound
778be232a207e (Andy Adamson 2011-01-25 15:38:01 +0000 429) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 430) static int nfs_callback_authenticate(struct svc_rqst *rqstp)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 431) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 432) switch (rqstp->rq_authop->flavour) {
778be232a207e (Andy Adamson 2011-01-25 15:38:01 +0000 433) case RPC_AUTH_NULL:
778be232a207e (Andy Adamson 2011-01-25 15:38:01 +0000 434) if (rqstp->rq_proc != CB_NULL)
6f02dc88be1d5 (Jeff Layton 2015-06-04 18:40:13 -0400 435) return SVC_DENIED;
778be232a207e (Andy Adamson 2011-01-25 15:38:01 +0000 436) break;
778be232a207e (Andy Adamson 2011-01-25 15:38:01 +0000 437) case RPC_AUTH_GSS:
778be232a207e (Andy Adamson 2011-01-25 15:38:01 +0000 438) /* No RPC_AUTH_GSS support yet in NFSv4.1 */
778be232a207e (Andy Adamson 2011-01-25 15:38:01 +0000 439) if (svc_is_backchannel(rqstp))
6f02dc88be1d5 (Jeff Layton 2015-06-04 18:40:13 -0400 440) return SVC_DENIED;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 441) }
778be232a207e (Andy Adamson 2011-01-25 15:38:01 +0000 442) return SVC_OK;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 443) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 444)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 445) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 446) * Define NFS4 callback program
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 447) */
e9679189e34b2 (Christoph Hellwig 2017-05-12 16:21:37 +0200 448) static const struct svc_version *nfs4_callback_version[] = {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 449) [1] = &nfs4_callback_version1,
07bccc2dd4e87 (Alexandros Batsakis 2009-12-05 13:19:01 -0500 450) [4] = &nfs4_callback_version4,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 451) };
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 452)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 453) static struct svc_stat nfs4_callback_stats;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 454)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 455) static struct svc_program nfs4_callback_program = {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 456) .pg_prog = NFS4_CALLBACK, /* RPC service number */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 457) .pg_nvers = ARRAY_SIZE(nfs4_callback_version), /* Number of entries */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 458) .pg_vers = nfs4_callback_version, /* version table */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 459) .pg_name = "NFSv4 callback", /* service name */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 460) .pg_class = "nfs", /* authentication class */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 461) .pg_stats = &nfs4_callback_stats,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 462) .pg_authenticate = nfs_callback_authenticate,
8e5b67731d088 (Trond Myklebust 2019-04-09 11:46:15 -0400 463) .pg_init_request = svc_generic_init_request,
642ee6b209c2f (Trond Myklebust 2019-04-09 11:46:17 -0400 464) .pg_rpcbind_set = svc_generic_rpcbind_set,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 465) };