ret = svc_xprt_create(serv, "tcp", net, PF_INET,
nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS,
cred); if (ret <= 0) goto out_err;
nn->nfs_callback_tcpport = ret;
dprintk("NFS: Callback listener port = %u (af %u, net %x)\n",
nn->nfs_callback_tcpport, PF_INET, net->ns.inum);
ret = svc_xprt_create(serv, "tcp", net, PF_INET6,
nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS,
cred); if (ret > 0) {
nn->nfs_callback_tcpport6 = ret;
dprintk("NFS: Callback listener port = %u (af %u, net %x)\n",
nn->nfs_callback_tcpport6, PF_INET6, net->ns.inum);
} elseif (ret != -EAFNOSUPPORT) goto out_err; return 0;
out_err: return (ret) ? ret : -ENOMEM;
}
/* * This is the NFSv4 callback kernel thread.
*/ staticint
nfs4_callback_svc(void *vrqstp)
{ struct svc_rqst *rqstp = vrqstp;
svc_thread_init_status(rqstp, 0);
set_freezable();
while (!svc_thread_should_stop(rqstp))
svc_recv(rqstp);
svc_exit_thread(rqstp); return 0;
}
#ifdefined(CONFIG_NFS_V4_1) staticinlinevoid nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt, struct svc_serv *serv)
{ if (minorversion) /* * Save the svc_serv in the transport so that it can * be referenced when the session backchannel is initialized
*/
xprt->bc_serv = serv;
} #else staticinlinevoid nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt, struct svc_serv *serv)
{
} #endif/* CONFIG_NFS_V4_1 */
staticint nfs_callback_start_svc(int minorversion, struct rpc_xprt *xprt, struct svc_serv *serv)
{ int nrservs = nfs_callback_nr_threads; int ret;
nfs_callback_bc_serv(minorversion, xprt, serv);
if (nrservs < NFS4_MIN_NR_CALLBACK_THREADS)
nrservs = NFS4_MIN_NR_CALLBACK_THREADS;
if (serv->sv_nrthreads == nrservs) return 0;
ret = svc_set_num_threads(serv, NULL, nrservs); if (ret) {
svc_set_num_threads(serv, NULL, 0); return ret;
}
dprintk("nfs_callback_up: service started\n"); return 0;
}
ret = svc_bind(serv, net); if (ret < 0) {
printk(KERN_WARNING "NFS: bind callback service failed\n"); goto err_bind;
}
ret = 0; if (!IS_ENABLED(CONFIG_NFS_V4_1) || minorversion == 0)
ret = nfs4_callback_up_net(serv, net); elseif (xprt->ops->bc_setup)
set_bc_enabled(serv); else
ret = -EPROTONOSUPPORT;
if (ret < 0) {
printk(KERN_ERR "NFS: callback service start failed\n"); goto err_socks;
} return 0;
/* * Check whether we're already up and running.
*/ if (cb_info->serv) return cb_info->serv;
/* * Sanity check: if there's no task, * we should be the first user ...
*/ if (cb_info->users)
printk(KERN_WARNING "nfs_callback_create_svc: no kthread, %d users??\n",
cb_info->users);
threadfn = nfs4_callback_svc; #if !defined(CONFIG_NFS_V4_1) if (minorversion) return ERR_PTR(-ENOTSUPP); #endif
serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE,
threadfn); if (!serv) {
printk(KERN_ERR "nfs_callback_create_svc: create service failed\n"); return ERR_PTR(-ENOMEM);
}
cb_info->serv = serv;
dprintk("nfs_callback_create_svc: service created\n"); return serv;
}
/* * Bring up the callback thread if it is not already up.
*/ int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt)
{ struct svc_serv *serv; struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion]; int ret; struct net *net = xprt->xprt_net;
mutex_lock(&nfs_callback_mutex);
serv = nfs_callback_create_svc(minorversion); if (IS_ERR(serv)) {
ret = PTR_ERR(serv); goto err_create;
}
ret = nfs_callback_up_net(minorversion, serv, net, xprt); if (ret < 0) goto err_net;
ret = nfs_callback_start_svc(minorversion, xprt, serv); if (ret < 0) goto err_start;
/* Boolean check of RPC_AUTH_GSS principal */ int
check_gss_callback_principal(struct nfs_client *clp, struct svc_rqst *rqstp)
{ char *p = rqstp->rq_cred.cr_principal;
if (rqstp->rq_authop->flavour != RPC_AUTH_GSS) return 1;
/* No RPC_AUTH_GSS on NFSv4.1 back channel yet */ if (clp->cl_minorversion != 0) return 0; /* * It might just be a normal user principal, in which case * userspace won't bother to tell us the name at all.
*/ if (p == NULL) return 0;
/* * Did we get the acceptor from userland during the SETCLIENID * negotiation?
*/ if (clp->cl_acceptor) return !strcmp(p, clp->cl_acceptor);
/* * Otherwise try to verify it using the cl_hostname. Note that this * doesn't work if a non-canonical hostname was used in the devname.
*/
/* Expect a GSS_C_NT_HOSTBASED_NAME like "nfs@serverhostname" */
if (memcmp(p, "nfs@", 4) != 0) return 0;
p += 4; if (strcmp(p, clp->cl_hostname) != 0) return 0; return 1;
}
/* * pg_authenticate method for nfsv4 callback threads. * * The authflavor has been negotiated, so an incorrect flavor is a server * bug. Deny packets with incorrect authflavor. * * All other checking done after NFS decoding where the nfs_client can be * found in nfs4_callback_compound
*/ staticenum svc_auth_status nfs_callback_authenticate(struct svc_rqst *rqstp)
{
rqstp->rq_auth_stat = rpc_autherr_badcred;
switch (rqstp->rq_authop->flavour) { case RPC_AUTH_NULL: if (rqstp->rq_proc != CB_NULL) return SVC_DENIED; break; case RPC_AUTH_GSS: /* No RPC_AUTH_GSS support yet in NFSv4.1 */ if (svc_is_backchannel(rqstp)) return SVC_DENIED;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.