162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * linux/fs/nfs/callback.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2004 Trond Myklebust 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * NFSv4 callback handling 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/completion.h> 1162306a36Sopenharmony_ci#include <linux/ip.h> 1262306a36Sopenharmony_ci#include <linux/module.h> 1362306a36Sopenharmony_ci#include <linux/sched/signal.h> 1462306a36Sopenharmony_ci#include <linux/sunrpc/svc.h> 1562306a36Sopenharmony_ci#include <linux/sunrpc/svcsock.h> 1662306a36Sopenharmony_ci#include <linux/nfs_fs.h> 1762306a36Sopenharmony_ci#include <linux/errno.h> 1862306a36Sopenharmony_ci#include <linux/mutex.h> 1962306a36Sopenharmony_ci#include <linux/freezer.h> 2062306a36Sopenharmony_ci#include <linux/sunrpc/svcauth_gss.h> 2162306a36Sopenharmony_ci#include <linux/sunrpc/bc_xprt.h> 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#include <net/inet_sock.h> 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#include "nfs4_fs.h" 2662306a36Sopenharmony_ci#include "callback.h" 2762306a36Sopenharmony_ci#include "internal.h" 2862306a36Sopenharmony_ci#include "netns.h" 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#define NFSDBG_FACILITY NFSDBG_CALLBACK 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_cistruct nfs_callback_data { 3362306a36Sopenharmony_ci unsigned int users; 3462306a36Sopenharmony_ci struct svc_serv *serv; 3562306a36Sopenharmony_ci}; 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_cistatic struct nfs_callback_data nfs_callback_info[NFS4_MAX_MINOR_VERSION + 1]; 3862306a36Sopenharmony_cistatic DEFINE_MUTEX(nfs_callback_mutex); 3962306a36Sopenharmony_cistatic struct svc_program nfs4_callback_program; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_cistatic int nfs4_callback_up_net(struct svc_serv *serv, struct net *net) 4262306a36Sopenharmony_ci{ 4362306a36Sopenharmony_ci const struct cred *cred = current_cred(); 4462306a36Sopenharmony_ci int ret; 4562306a36Sopenharmony_ci struct nfs_net *nn = net_generic(net, nfs_net_id); 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci ret = svc_xprt_create(serv, "tcp", net, PF_INET, 4862306a36Sopenharmony_ci nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS, 4962306a36Sopenharmony_ci cred); 5062306a36Sopenharmony_ci if (ret <= 0) 5162306a36Sopenharmony_ci goto out_err; 5262306a36Sopenharmony_ci nn->nfs_callback_tcpport = ret; 5362306a36Sopenharmony_ci dprintk("NFS: Callback listener port = %u (af %u, net %x)\n", 5462306a36Sopenharmony_ci nn->nfs_callback_tcpport, PF_INET, net->ns.inum); 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci ret = svc_xprt_create(serv, "tcp", net, PF_INET6, 5762306a36Sopenharmony_ci nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS, 5862306a36Sopenharmony_ci cred); 5962306a36Sopenharmony_ci if (ret > 0) { 6062306a36Sopenharmony_ci nn->nfs_callback_tcpport6 = ret; 6162306a36Sopenharmony_ci dprintk("NFS: Callback listener port = %u (af %u, net %x)\n", 6262306a36Sopenharmony_ci nn->nfs_callback_tcpport6, PF_INET6, net->ns.inum); 6362306a36Sopenharmony_ci } else if (ret != -EAFNOSUPPORT) 6462306a36Sopenharmony_ci goto out_err; 6562306a36Sopenharmony_ci return 0; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ciout_err: 6862306a36Sopenharmony_ci return (ret) ? ret : -ENOMEM; 6962306a36Sopenharmony_ci} 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci/* 7262306a36Sopenharmony_ci * This is the NFSv4 callback kernel thread. 7362306a36Sopenharmony_ci */ 7462306a36Sopenharmony_cistatic int 7562306a36Sopenharmony_cinfs4_callback_svc(void *vrqstp) 7662306a36Sopenharmony_ci{ 7762306a36Sopenharmony_ci struct svc_rqst *rqstp = vrqstp; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci set_freezable(); 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci while (!kthread_freezable_should_stop(NULL)) 8262306a36Sopenharmony_ci svc_recv(rqstp); 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci svc_exit_thread(rqstp); 8562306a36Sopenharmony_ci return 0; 8662306a36Sopenharmony_ci} 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci#if defined(CONFIG_NFS_V4_1) 8962306a36Sopenharmony_ci/* 9062306a36Sopenharmony_ci * The callback service for NFSv4.1 callbacks 9162306a36Sopenharmony_ci */ 9262306a36Sopenharmony_cistatic int 9362306a36Sopenharmony_cinfs41_callback_svc(void *vrqstp) 9462306a36Sopenharmony_ci{ 9562306a36Sopenharmony_ci struct svc_rqst *rqstp = vrqstp; 9662306a36Sopenharmony_ci struct svc_serv *serv = rqstp->rq_server; 9762306a36Sopenharmony_ci struct rpc_rqst *req; 9862306a36Sopenharmony_ci int error; 9962306a36Sopenharmony_ci DEFINE_WAIT(wq); 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci set_freezable(); 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci while (!kthread_freezable_should_stop(NULL)) { 10462306a36Sopenharmony_ci prepare_to_wait(&serv->sv_cb_waitq, &wq, TASK_IDLE); 10562306a36Sopenharmony_ci spin_lock_bh(&serv->sv_cb_lock); 10662306a36Sopenharmony_ci if (!list_empty(&serv->sv_cb_list)) { 10762306a36Sopenharmony_ci req = list_first_entry(&serv->sv_cb_list, 10862306a36Sopenharmony_ci struct rpc_rqst, rq_bc_list); 10962306a36Sopenharmony_ci list_del(&req->rq_bc_list); 11062306a36Sopenharmony_ci spin_unlock_bh(&serv->sv_cb_lock); 11162306a36Sopenharmony_ci finish_wait(&serv->sv_cb_waitq, &wq); 11262306a36Sopenharmony_ci dprintk("Invoking bc_svc_process()\n"); 11362306a36Sopenharmony_ci error = bc_svc_process(serv, req, rqstp); 11462306a36Sopenharmony_ci dprintk("bc_svc_process() returned w/ error code= %d\n", 11562306a36Sopenharmony_ci error); 11662306a36Sopenharmony_ci } else { 11762306a36Sopenharmony_ci spin_unlock_bh(&serv->sv_cb_lock); 11862306a36Sopenharmony_ci if (!kthread_should_stop()) 11962306a36Sopenharmony_ci schedule(); 12062306a36Sopenharmony_ci finish_wait(&serv->sv_cb_waitq, &wq); 12162306a36Sopenharmony_ci } 12262306a36Sopenharmony_ci } 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci svc_exit_thread(rqstp); 12562306a36Sopenharmony_ci return 0; 12662306a36Sopenharmony_ci} 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_cistatic inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt, 12962306a36Sopenharmony_ci struct svc_serv *serv) 13062306a36Sopenharmony_ci{ 13162306a36Sopenharmony_ci if (minorversion) 13262306a36Sopenharmony_ci /* 13362306a36Sopenharmony_ci * Save the svc_serv in the transport so that it can 13462306a36Sopenharmony_ci * be referenced when the session backchannel is initialized 13562306a36Sopenharmony_ci */ 13662306a36Sopenharmony_ci xprt->bc_serv = serv; 13762306a36Sopenharmony_ci} 13862306a36Sopenharmony_ci#else 13962306a36Sopenharmony_cistatic inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt, 14062306a36Sopenharmony_ci struct svc_serv *serv) 14162306a36Sopenharmony_ci{ 14262306a36Sopenharmony_ci} 14362306a36Sopenharmony_ci#endif /* CONFIG_NFS_V4_1 */ 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_cistatic int nfs_callback_start_svc(int minorversion, struct rpc_xprt *xprt, 14662306a36Sopenharmony_ci struct svc_serv *serv) 14762306a36Sopenharmony_ci{ 14862306a36Sopenharmony_ci int nrservs = nfs_callback_nr_threads; 14962306a36Sopenharmony_ci int ret; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci nfs_callback_bc_serv(minorversion, xprt, serv); 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci if (nrservs < NFS4_MIN_NR_CALLBACK_THREADS) 15462306a36Sopenharmony_ci nrservs = NFS4_MIN_NR_CALLBACK_THREADS; 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci if (serv->sv_nrthreads == nrservs) 15762306a36Sopenharmony_ci return 0; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci ret = svc_set_num_threads(serv, NULL, nrservs); 16062306a36Sopenharmony_ci if (ret) { 16162306a36Sopenharmony_ci svc_set_num_threads(serv, NULL, 0); 16262306a36Sopenharmony_ci return ret; 16362306a36Sopenharmony_ci } 16462306a36Sopenharmony_ci dprintk("nfs_callback_up: service started\n"); 16562306a36Sopenharmony_ci return 0; 16662306a36Sopenharmony_ci} 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_cistatic void nfs_callback_down_net(u32 minorversion, struct svc_serv *serv, struct net *net) 16962306a36Sopenharmony_ci{ 17062306a36Sopenharmony_ci struct nfs_net *nn = net_generic(net, nfs_net_id); 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci if (--nn->cb_users[minorversion]) 17362306a36Sopenharmony_ci return; 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci dprintk("NFS: destroy per-net callback data; net=%x\n", net->ns.inum); 17662306a36Sopenharmony_ci svc_xprt_destroy_all(serv, net); 17762306a36Sopenharmony_ci} 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_cistatic int nfs_callback_up_net(int minorversion, struct svc_serv *serv, 18062306a36Sopenharmony_ci struct net *net, struct rpc_xprt *xprt) 18162306a36Sopenharmony_ci{ 18262306a36Sopenharmony_ci struct nfs_net *nn = net_generic(net, nfs_net_id); 18362306a36Sopenharmony_ci int ret; 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci if (nn->cb_users[minorversion]++) 18662306a36Sopenharmony_ci return 0; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci dprintk("NFS: create per-net callback data; net=%x\n", net->ns.inum); 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci ret = svc_bind(serv, net); 19162306a36Sopenharmony_ci if (ret < 0) { 19262306a36Sopenharmony_ci printk(KERN_WARNING "NFS: bind callback service failed\n"); 19362306a36Sopenharmony_ci goto err_bind; 19462306a36Sopenharmony_ci } 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci ret = 0; 19762306a36Sopenharmony_ci if (!IS_ENABLED(CONFIG_NFS_V4_1) || minorversion == 0) 19862306a36Sopenharmony_ci ret = nfs4_callback_up_net(serv, net); 19962306a36Sopenharmony_ci else if (xprt->ops->bc_setup) 20062306a36Sopenharmony_ci set_bc_enabled(serv); 20162306a36Sopenharmony_ci else 20262306a36Sopenharmony_ci ret = -EPROTONOSUPPORT; 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci if (ret < 0) { 20562306a36Sopenharmony_ci printk(KERN_ERR "NFS: callback service start failed\n"); 20662306a36Sopenharmony_ci goto err_socks; 20762306a36Sopenharmony_ci } 20862306a36Sopenharmony_ci return 0; 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_cierr_socks: 21162306a36Sopenharmony_ci svc_rpcb_cleanup(serv, net); 21262306a36Sopenharmony_cierr_bind: 21362306a36Sopenharmony_ci nn->cb_users[minorversion]--; 21462306a36Sopenharmony_ci dprintk("NFS: Couldn't create callback socket: err = %d; " 21562306a36Sopenharmony_ci "net = %x\n", ret, net->ns.inum); 21662306a36Sopenharmony_ci return ret; 21762306a36Sopenharmony_ci} 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_cistatic struct svc_serv *nfs_callback_create_svc(int minorversion) 22062306a36Sopenharmony_ci{ 22162306a36Sopenharmony_ci struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion]; 22262306a36Sopenharmony_ci int (*threadfn)(void *data); 22362306a36Sopenharmony_ci struct svc_serv *serv; 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci /* 22662306a36Sopenharmony_ci * Check whether we're already up and running. 22762306a36Sopenharmony_ci */ 22862306a36Sopenharmony_ci if (cb_info->serv) 22962306a36Sopenharmony_ci return svc_get(cb_info->serv); 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci /* 23262306a36Sopenharmony_ci * Sanity check: if there's no task, 23362306a36Sopenharmony_ci * we should be the first user ... 23462306a36Sopenharmony_ci */ 23562306a36Sopenharmony_ci if (cb_info->users) 23662306a36Sopenharmony_ci printk(KERN_WARNING "nfs_callback_create_svc: no kthread, %d users??\n", 23762306a36Sopenharmony_ci cb_info->users); 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci threadfn = nfs4_callback_svc; 24062306a36Sopenharmony_ci#if defined(CONFIG_NFS_V4_1) 24162306a36Sopenharmony_ci if (minorversion) 24262306a36Sopenharmony_ci threadfn = nfs41_callback_svc; 24362306a36Sopenharmony_ci#else 24462306a36Sopenharmony_ci if (minorversion) 24562306a36Sopenharmony_ci return ERR_PTR(-ENOTSUPP); 24662306a36Sopenharmony_ci#endif 24762306a36Sopenharmony_ci serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, 24862306a36Sopenharmony_ci threadfn); 24962306a36Sopenharmony_ci if (!serv) { 25062306a36Sopenharmony_ci printk(KERN_ERR "nfs_callback_create_svc: create service failed\n"); 25162306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 25262306a36Sopenharmony_ci } 25362306a36Sopenharmony_ci cb_info->serv = serv; 25462306a36Sopenharmony_ci /* As there is only one thread we need to over-ride the 25562306a36Sopenharmony_ci * default maximum of 80 connections 25662306a36Sopenharmony_ci */ 25762306a36Sopenharmony_ci serv->sv_maxconn = 1024; 25862306a36Sopenharmony_ci dprintk("nfs_callback_create_svc: service created\n"); 25962306a36Sopenharmony_ci return serv; 26062306a36Sopenharmony_ci} 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci/* 26362306a36Sopenharmony_ci * Bring up the callback thread if it is not already up. 26462306a36Sopenharmony_ci */ 26562306a36Sopenharmony_ciint nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt) 26662306a36Sopenharmony_ci{ 26762306a36Sopenharmony_ci struct svc_serv *serv; 26862306a36Sopenharmony_ci struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion]; 26962306a36Sopenharmony_ci int ret; 27062306a36Sopenharmony_ci struct net *net = xprt->xprt_net; 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci mutex_lock(&nfs_callback_mutex); 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci serv = nfs_callback_create_svc(minorversion); 27562306a36Sopenharmony_ci if (IS_ERR(serv)) { 27662306a36Sopenharmony_ci ret = PTR_ERR(serv); 27762306a36Sopenharmony_ci goto err_create; 27862306a36Sopenharmony_ci } 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci ret = nfs_callback_up_net(minorversion, serv, net, xprt); 28162306a36Sopenharmony_ci if (ret < 0) 28262306a36Sopenharmony_ci goto err_net; 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci ret = nfs_callback_start_svc(minorversion, xprt, serv); 28562306a36Sopenharmony_ci if (ret < 0) 28662306a36Sopenharmony_ci goto err_start; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci cb_info->users++; 28962306a36Sopenharmony_cierr_net: 29062306a36Sopenharmony_ci if (!cb_info->users) 29162306a36Sopenharmony_ci cb_info->serv = NULL; 29262306a36Sopenharmony_ci svc_put(serv); 29362306a36Sopenharmony_cierr_create: 29462306a36Sopenharmony_ci mutex_unlock(&nfs_callback_mutex); 29562306a36Sopenharmony_ci return ret; 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_cierr_start: 29862306a36Sopenharmony_ci nfs_callback_down_net(minorversion, serv, net); 29962306a36Sopenharmony_ci dprintk("NFS: Couldn't create server thread; err = %d\n", ret); 30062306a36Sopenharmony_ci goto err_net; 30162306a36Sopenharmony_ci} 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci/* 30462306a36Sopenharmony_ci * Kill the callback thread if it's no longer being used. 30562306a36Sopenharmony_ci */ 30662306a36Sopenharmony_civoid nfs_callback_down(int minorversion, struct net *net) 30762306a36Sopenharmony_ci{ 30862306a36Sopenharmony_ci struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion]; 30962306a36Sopenharmony_ci struct svc_serv *serv; 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci mutex_lock(&nfs_callback_mutex); 31262306a36Sopenharmony_ci serv = cb_info->serv; 31362306a36Sopenharmony_ci nfs_callback_down_net(minorversion, serv, net); 31462306a36Sopenharmony_ci cb_info->users--; 31562306a36Sopenharmony_ci if (cb_info->users == 0) { 31662306a36Sopenharmony_ci svc_get(serv); 31762306a36Sopenharmony_ci svc_set_num_threads(serv, NULL, 0); 31862306a36Sopenharmony_ci svc_put(serv); 31962306a36Sopenharmony_ci dprintk("nfs_callback_down: service destroyed\n"); 32062306a36Sopenharmony_ci cb_info->serv = NULL; 32162306a36Sopenharmony_ci } 32262306a36Sopenharmony_ci mutex_unlock(&nfs_callback_mutex); 32362306a36Sopenharmony_ci} 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci/* Boolean check of RPC_AUTH_GSS principal */ 32662306a36Sopenharmony_ciint 32762306a36Sopenharmony_cicheck_gss_callback_principal(struct nfs_client *clp, struct svc_rqst *rqstp) 32862306a36Sopenharmony_ci{ 32962306a36Sopenharmony_ci char *p = rqstp->rq_cred.cr_principal; 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci if (rqstp->rq_authop->flavour != RPC_AUTH_GSS) 33262306a36Sopenharmony_ci return 1; 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci /* No RPC_AUTH_GSS on NFSv4.1 back channel yet */ 33562306a36Sopenharmony_ci if (clp->cl_minorversion != 0) 33662306a36Sopenharmony_ci return 0; 33762306a36Sopenharmony_ci /* 33862306a36Sopenharmony_ci * It might just be a normal user principal, in which case 33962306a36Sopenharmony_ci * userspace won't bother to tell us the name at all. 34062306a36Sopenharmony_ci */ 34162306a36Sopenharmony_ci if (p == NULL) 34262306a36Sopenharmony_ci return 0; 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci /* 34562306a36Sopenharmony_ci * Did we get the acceptor from userland during the SETCLIENID 34662306a36Sopenharmony_ci * negotiation? 34762306a36Sopenharmony_ci */ 34862306a36Sopenharmony_ci if (clp->cl_acceptor) 34962306a36Sopenharmony_ci return !strcmp(p, clp->cl_acceptor); 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci /* 35262306a36Sopenharmony_ci * Otherwise try to verify it using the cl_hostname. Note that this 35362306a36Sopenharmony_ci * doesn't work if a non-canonical hostname was used in the devname. 35462306a36Sopenharmony_ci */ 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci /* Expect a GSS_C_NT_HOSTBASED_NAME like "nfs@serverhostname" */ 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci if (memcmp(p, "nfs@", 4) != 0) 35962306a36Sopenharmony_ci return 0; 36062306a36Sopenharmony_ci p += 4; 36162306a36Sopenharmony_ci if (strcmp(p, clp->cl_hostname) != 0) 36262306a36Sopenharmony_ci return 0; 36362306a36Sopenharmony_ci return 1; 36462306a36Sopenharmony_ci} 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci/* 36762306a36Sopenharmony_ci * pg_authenticate method for nfsv4 callback threads. 36862306a36Sopenharmony_ci * 36962306a36Sopenharmony_ci * The authflavor has been negotiated, so an incorrect flavor is a server 37062306a36Sopenharmony_ci * bug. Deny packets with incorrect authflavor. 37162306a36Sopenharmony_ci * 37262306a36Sopenharmony_ci * All other checking done after NFS decoding where the nfs_client can be 37362306a36Sopenharmony_ci * found in nfs4_callback_compound 37462306a36Sopenharmony_ci */ 37562306a36Sopenharmony_cistatic enum svc_auth_status nfs_callback_authenticate(struct svc_rqst *rqstp) 37662306a36Sopenharmony_ci{ 37762306a36Sopenharmony_ci rqstp->rq_auth_stat = rpc_autherr_badcred; 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci switch (rqstp->rq_authop->flavour) { 38062306a36Sopenharmony_ci case RPC_AUTH_NULL: 38162306a36Sopenharmony_ci if (rqstp->rq_proc != CB_NULL) 38262306a36Sopenharmony_ci return SVC_DENIED; 38362306a36Sopenharmony_ci break; 38462306a36Sopenharmony_ci case RPC_AUTH_GSS: 38562306a36Sopenharmony_ci /* No RPC_AUTH_GSS support yet in NFSv4.1 */ 38662306a36Sopenharmony_ci if (svc_is_backchannel(rqstp)) 38762306a36Sopenharmony_ci return SVC_DENIED; 38862306a36Sopenharmony_ci } 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci rqstp->rq_auth_stat = rpc_auth_ok; 39162306a36Sopenharmony_ci return SVC_OK; 39262306a36Sopenharmony_ci} 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci/* 39562306a36Sopenharmony_ci * Define NFS4 callback program 39662306a36Sopenharmony_ci */ 39762306a36Sopenharmony_cistatic const struct svc_version *nfs4_callback_version[] = { 39862306a36Sopenharmony_ci [1] = &nfs4_callback_version1, 39962306a36Sopenharmony_ci [4] = &nfs4_callback_version4, 40062306a36Sopenharmony_ci}; 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_cistatic struct svc_stat nfs4_callback_stats; 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_cistatic struct svc_program nfs4_callback_program = { 40562306a36Sopenharmony_ci .pg_prog = NFS4_CALLBACK, /* RPC service number */ 40662306a36Sopenharmony_ci .pg_nvers = ARRAY_SIZE(nfs4_callback_version), /* Number of entries */ 40762306a36Sopenharmony_ci .pg_vers = nfs4_callback_version, /* version table */ 40862306a36Sopenharmony_ci .pg_name = "NFSv4 callback", /* service name */ 40962306a36Sopenharmony_ci .pg_class = "nfs", /* authentication class */ 41062306a36Sopenharmony_ci .pg_stats = &nfs4_callback_stats, 41162306a36Sopenharmony_ci .pg_authenticate = nfs_callback_authenticate, 41262306a36Sopenharmony_ci .pg_init_request = svc_generic_init_request, 41362306a36Sopenharmony_ci .pg_rpcbind_set = svc_generic_rpcbind_set, 41462306a36Sopenharmony_ci}; 415