void svc_authenticate(struct svc_rqst *rqstp, u32 *statp, u32 *authp) { u32 flavor; auth_fn_t func; *statp = rpc_success; *authp = rpc_auth_ok; svc_getlong(&rqstp->rq_argbuf, flavor); flavor = ntohl(flavor); dprintk("svc: svc_authenticate (%d)\n", flavor); if (flavor >= RPC_SVCAUTH_MAX || !(func = authtab[flavor])) { *authp = rpc_autherr_badcred; return; } rqstp->rq_cred.cr_flavor = flavor; func(rqstp, statp, authp); }
/* * Receive the next request on any socket. */ int svc_recv(struct svc_serv *serv, struct svc_rqst *rqstp, long timeout) { struct svc_sock *svsk; int len; DECLARE_WAITQUEUE(wait, current); dprintk("svc: server %p waiting for data (to = %ld)\n", rqstp, timeout); if (rqstp->rq_sock) printk(KERN_ERR "svc_recv: service %p, socket not NULL!\n", rqstp); if (waitqueue_active(&rqstp->rq_wait)) printk(KERN_ERR "svc_recv: service %p, wait queue active!\n", rqstp); /* Initialize the buffers */ rqstp->rq_argbuf = rqstp->rq_defbuf; rqstp->rq_resbuf = rqstp->rq_defbuf; if (signalled()) return -EINTR; spin_lock_bh(&serv->sv_lock); if ((svsk = svc_sock_dequeue(serv)) != NULL) { rqstp->rq_sock = svsk; svsk->sk_inuse++; } else { /* No data pending. Go to sleep */ svc_serv_enqueue(serv, rqstp); /* * We have to be able to interrupt this wait * to bring down the daemons ... */ set_current_state(TASK_INTERRUPTIBLE); add_wait_queue(&rqstp->rq_wait, &wait); spin_unlock_bh(&serv->sv_lock); schedule_timeout(timeout); spin_lock_bh(&serv->sv_lock); remove_wait_queue(&rqstp->rq_wait, &wait); if (!(svsk = rqstp->rq_sock)) { svc_serv_dequeue(serv, rqstp); spin_unlock_bh(&serv->sv_lock); dprintk("svc: server %p, no data yet\n", rqstp); return signalled()? -EINTR : -EAGAIN; } } spin_unlock_bh(&serv->sv_lock); dprintk("svc: server %p, socket %p, inuse=%d\n", rqstp, svsk, svsk->sk_inuse); len = svsk->sk_recvfrom(rqstp); dprintk("svc: got len=%d\n", len); /* No data, incomplete (TCP) read, or accept() */ if (len == 0 || len == -EAGAIN) { svc_sock_release(rqstp); return -EAGAIN; } rqstp->rq_secure = ntohs(rqstp->rq_addr.sin_port) < 1024; rqstp->rq_userset = 0; rqstp->rq_verfed = 0; svc_getlong(&rqstp->rq_argbuf, rqstp->rq_xid); svc_putlong(&rqstp->rq_resbuf, rqstp->rq_xid); /* Assume that the reply consists of a single buffer. */ rqstp->rq_resbuf.nriov = 1; if (serv->sv_stats) serv->sv_stats->netcnt++; return len; }