Date: Tue, 16 Jul 2013 00:05:17 +0000 (UTC) From: Rick Macklem <rmacklem@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r253375 - projects/nfsv4.1-server/sys/fs/nfsserver Message-ID: <201307160005.r6G05H7L001796@svn.freebsd.org>
index | next in thread | raw e-mail
Author: rmacklem Date: Tue Jul 16 00:05:17 2013 New Revision: 253375 URL: http://svnweb.freebsd.org/changeset/base/253375 Log: Merge in changes for the NFSv4.1 server to the first 4 files. More to come soon. Modified: projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdcache.c projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdkrpc.c projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdport.c projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdserv.c Modified: projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdcache.c ============================================================================== --- projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdcache.c Mon Jul 15 23:27:48 2013 (r253374) +++ projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdcache.c Tue Jul 16 00:05:17 2013 (r253375) @@ -811,6 +811,9 @@ APPLESTATIC void nfsrvd_refcache(struct nfsrvcache *rp) { + if (rp == NULL) + /* For NFSv4.1, there is no cache entry. */ + return; NFSLOCKCACHE(); if (rp->rc_refcnt < 0) panic("nfs cache refcnt"); Modified: projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdkrpc.c ============================================================================== --- projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdkrpc.c Mon Jul 15 23:27:48 2013 (r253374) +++ projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdkrpc.c Tue Jul 16 00:05:17 2013 (r253375) @@ -304,7 +304,10 @@ nfs_proc(struct nfsrv_descript *nd, u_in u_int64_t sockref, struct nfsrvcache **rpp) { struct thread *td = curthread; - int cacherep = RC_DOIT, isdgram; + int cacherep = RC_DOIT, isdgram, taglen = -1; + struct mbuf *m; + u_char tag[NFSV4_SMALLSTR + 1], *tagstr = NULL; + u_int32_t minorvers = 0; *rpp = NULL; if (nd->nd_nam2 == NULL) { @@ -337,7 +340,14 @@ nfs_proc(struct nfsrv_descript *nd, u_in nd->nd_retxid = xid; nd->nd_tcpconntime = NFSD_MONOSEC; nd->nd_sockref = sockref; - cacherep = nfsrvd_getcache(nd, so); + if ((nd->nd_flag & ND_NFSV4) != 0) + nfsd_getminorvers(nd, tag, &tagstr, &taglen, + &minorvers); + if ((nd->nd_flag & ND_NFSV41) != 0) + /* NFSv4.1 caches replies in the session slots. */ + cacherep = RC_DOIT; + else + cacherep = nfsrvd_getcache(nd, so); } /* @@ -347,13 +357,31 @@ nfs_proc(struct nfsrv_descript *nd, u_in * RC_DROPIT - just throw the request away */ if (cacherep == RC_DOIT) { - nfsrvd_dorpc(nd, isdgram, td); - if (nd->nd_repstat == NFSERR_DONTREPLY) - cacherep = RC_DROPIT; - else + nfsrvd_dorpc(nd, isdgram, tagstr, taglen, minorvers, td); + if ((nd->nd_flag & ND_NFSV41) != 0) { + if (nd->nd_repstat != NFSERR_REPLYFROMCACHE && + (nd->nd_flag & ND_SAVEREPLY) != 0) { + /* Cache a copy of the reply. */ + m = m_copym(nd->nd_mreq, 0, M_COPYALL, + M_WAITOK); + } else + m = NULL; + if ((nd->nd_flag & ND_HASSEQUENCE) != 0) + nfsrv_cache_session(nd->nd_sessionid, + nd->nd_slotid, nd->nd_repstat, &m); + if (nd->nd_repstat == NFSERR_REPLYFROMCACHE) + nd->nd_repstat = 0; cacherep = RC_REPLY; - *rpp = nfsrvd_updatecache(nd, so); + } else { + if (nd->nd_repstat == NFSERR_DONTREPLY) + cacherep = RC_DROPIT; + else + cacherep = RC_REPLY; + *rpp = nfsrvd_updatecache(nd, so); + } } + if (tagstr != NULL && taglen > NFSV4_SMALLSTR) + free(tagstr, M_TEMP); NFSEXITCODE2(0, nd); return (cacherep); Modified: projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdport.c ============================================================================== --- projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdport.c Mon Jul 15 23:27:48 2013 (r253374) +++ projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdport.c Tue Jul 16 00:05:17 2013 (r253375) @@ -58,6 +58,7 @@ extern struct nfsrv_stablefirst nfsrv_st extern void (*nfsd_call_servertimer)(void); extern SVCPOOL *nfsrvd_pool; extern struct nfsv4lock nfsd_suspend_lock; +extern struct nfssessionhash nfssessionhash[NFSSESSIONHASHSIZE]; struct vfsoptlist nfsv4root_opt, nfsv4root_newopt; NFSDLOCKMUTEX; struct mtx nfs_cache_mutex; @@ -65,6 +66,7 @@ struct mtx nfs_v4root_mutex; struct nfsrvfh nfs_rootfh, nfs_pubfh; int nfs_pubfhset = 0, nfs_rootfhset = 0; struct proc *nfsd_master_proc = NULL; +int nfsd_debuglevel = 0; static pid_t nfsd_master_pid = (pid_t)-1; static char nfsd_master_comm[MAXCOMLEN + 1]; static struct timeval nfsd_master_start; @@ -90,6 +92,8 @@ SYSCTL_INT(_vfs_nfsd, OID_AUTO, issue_de &nfsrv_issuedelegs, 0, "Enable nfsd to issue delegations"); SYSCTL_INT(_vfs_nfsd, OID_AUTO, enable_locallocks, CTLFLAG_RW, &nfsrv_dolocallocks, 0, "Enable nfsd to acquire local locks on files"); +SYSCTL_INT(_vfs_nfsd, OID_AUTO, debuglevel, CTLFLAG_RW, &nfsd_debuglevel, + 0, "Debug level for new nfs server"); #define MAX_REORDERED_RPC 16 #define NUM_HEURISTIC 1031 @@ -3245,6 +3249,18 @@ nfsrv_hashfh(fhandle_t *fhp) } /* + * Calculate a hash value for the sessionid. + */ +uint32_t +nfsrv_hashsessionid(uint8_t *sessionid) +{ + uint32_t hashval; + + hashval = hash32_buf(sessionid, NFSX_V4SESSIONID, 0); + return (hashval); +} + +/* * Signal the userland master nfsd to backup the stable restart file. */ void @@ -3278,7 +3294,7 @@ extern int (*nfsd_call_nfsd)(struct thre static int nfsd_modevent(module_t mod, int type, void *data) { - int error = 0; + int error = 0, i; static int loaded = 0; switch (type) { @@ -3290,6 +3306,9 @@ nfsd_modevent(module_t mod, int type, vo mtx_init(&nfs_v4root_mutex, "nfs_v4root_mutex", NULL, MTX_DEF); mtx_init(&nfsv4root_mnt.mnt_mtx, "struct mount mtx", NULL, MTX_DEF); + for (i = 0; i < NFSSESSIONHASHSIZE; i++) + mtx_init(&nfssessionhash[i].mtx, "nfs_session_mutex", + NULL, MTX_DEF); lockinit(&nfsv4root_mnt.mnt_explock, PVFS, "explock", 0, 0); nfsrvd_initcache(); nfsd_init(); @@ -3333,6 +3352,8 @@ nfsd_modevent(module_t mod, int type, vo mtx_destroy(&nfs_cache_mutex); mtx_destroy(&nfs_v4root_mutex); mtx_destroy(&nfsv4root_mnt.mnt_mtx); + for (i = 0; i < NFSSESSIONHASHSIZE; i++) + mtx_destroy(&nfssessionhash[i].mtx); lockdestroy(&nfsv4root_mnt.mnt_explock); loaded = 0; break; Modified: projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdserv.c ============================================================================== --- projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdserv.c Mon Jul 15 23:27:48 2013 (r253374) +++ projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdserv.c Tue Jul 16 00:05:17 2013 (r253375) @@ -2523,7 +2523,7 @@ nfsrvd_open(struct nfsrv_descript *nd, _ struct nfsexstuff *exp) { u_int32_t *tl; - int i; + int i, retext; struct nfsstate *stp = NULL; int error = 0, create, claim, exclusive_flag = 0; u_int32_t rflags = NFSV4OPEN_LOCKTYPEPOSIX, acemask; @@ -2560,6 +2560,16 @@ nfsrvd_open(struct nfsrv_descript *nd, _ stp->ls_uid = nd->nd_cred->cr_uid; stp->ls_seq = fxdr_unsigned(u_int32_t, *tl++); i = fxdr_unsigned(int, *tl++); + retext = -1; + if ((i & (NFSV4OPEN_WANTDELEGMASK | NFSV4OPEN_WANTSIGNALDELEG | + NFSV4OPEN_WANTPUSHDELEG)) != 0 && (nd->nd_flag & ND_NFSV41) != 0) { + retext = NFSV4OPEN_RESOURCE; + if ((i & (NFSV4OPEN_WANTDELEGMASK | NFSV4OPEN_WANTSIGNALDELEG | + NFSV4OPEN_WANTPUSHDELEG)) == NFSV4OPEN_WANTNODELEG) + retext = NFSV4OPEN_NOTWANTED; + i &= ~(NFSV4OPEN_WANTDELEGMASK | NFSV4OPEN_WANTSIGNALDELEG | + NFSV4OPEN_WANTPUSHDELEG); + } switch (i) { case NFSV4OPEN_ACCESSREAD: stp->ls_flags |= NFSLCK_READACCESS; @@ -2634,6 +2644,28 @@ nfsrvd_open(struct nfsrv_descript *nd, _ cverf[0] = *tl++; cverf[1] = *tl; break; + case NFSCREATE_EXCLUSIVE41: + NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF); + cverf[0] = *tl++; + cverf[1] = *tl; + error = nfsv4_sattr(nd, &nva, &attrbits, aclp, p); + if (error != 0) + goto nfsmout; + if (NFSISSET_ATTRBIT(&attrbits, + NFSATTRBIT_TIMEACCESSSET)) + nd->nd_repstat = NFSERR_INVAL; + /* + * If the na_gid being set is the same as that of + * the directory it is going in, clear it, since + * that is what will be set by default. This allows + * a user that isn't in that group to do the create. + */ + if (nd->nd_repstat == 0 && NFSVNO_ISSETGID(&nva) && + nva.na_gid == dirfor.na_gid) + NFSVNO_UNSET(&nva, gid); + if (nd->nd_repstat == 0) + nd->nd_repstat = nfsrv_checkuidgid(nd, &nva); + break; default: nd->nd_repstat = NFSERR_BADXDR; goto nfsmout; @@ -2715,27 +2747,38 @@ nfsrvd_open(struct nfsrv_descript *nd, _ exclusive_flag = 1; if (!named.ni_vp) nva.na_mode = 0; + break; + case NFSCREATE_EXCLUSIVE41: + exclusive_flag = 1; + break; }; } nfsvno_open(nd, &named, clientid, &stateid, stp, &exclusive_flag, &nva, cverf, create, aclp, &attrbits, nd->nd_cred, p, exp, &vp); - } else if (claim == NFSV4OPEN_CLAIMPREVIOUS) { - NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); - i = fxdr_unsigned(int, *tl); - switch (i) { - case NFSV4OPEN_DELEGATEREAD: - stp->ls_flags |= NFSLCK_DELEGREAD; - break; - case NFSV4OPEN_DELEGATEWRITE: - stp->ls_flags |= NFSLCK_DELEGWRITE; - case NFSV4OPEN_DELEGATENONE: - break; - default: - nd->nd_repstat = NFSERR_BADXDR; - goto nfsmout; - }; - stp->ls_flags |= NFSLCK_RECLAIM; + } else if (claim == NFSV4OPEN_CLAIMPREVIOUS || claim == + NFSV4OPEN_CLAIMFH) { + if (claim == NFSV4OPEN_CLAIMPREVIOUS) { + NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); + i = fxdr_unsigned(int, *tl); + switch (i) { + case NFSV4OPEN_DELEGATEREAD: + stp->ls_flags |= NFSLCK_DELEGREAD; + break; + case NFSV4OPEN_DELEGATEWRITE: + stp->ls_flags |= NFSLCK_DELEGWRITE; + case NFSV4OPEN_DELEGATENONE: + break; + default: + nd->nd_repstat = NFSERR_BADXDR; + goto nfsmout; + }; + stp->ls_flags |= NFSLCK_RECLAIM; + } else { + /* CLAIM_NULL_FH */ + if (nd->nd_repstat == 0 && create == NFSV4OPEN_CREATE) + nd->nd_repstat = NFSERR_INVAL; + } vp = dp; NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY); if ((vp->v_iflag & VI_DOOMED) == 0) @@ -2824,7 +2867,18 @@ nfsrvd_open(struct nfsrv_descript *nd, _ *tl = txdr_unsigned(NFSV4OPEN_DELEGATEREAD); else if (rflags & NFSV4OPEN_WRITEDELEGATE) *tl = txdr_unsigned(NFSV4OPEN_DELEGATEWRITE); - else + else if (retext != -1) { + *tl = txdr_unsigned(NFSV4OPEN_DELEGATENONEEXT); + if (retext == NFSV4OPEN_RESOURCE || + retext == NFSV4OPEN_CONTENTION) { + NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); + *tl++ = txdr_unsigned(retext); + *tl = newnfs_false; + } else { + NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); + *tl = txdr_unsigned(retext); + } + } else *tl = txdr_unsigned(NFSV4OPEN_DELEGATENONE); if (rflags & (NFSV4OPEN_READDELEGATE|NFSV4OPEN_WRITEDELEGATE)) { NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID+NFSX_UNSIGNED); @@ -2947,7 +3001,7 @@ nfsrvd_delegpurge(struct nfsrv_descript nd->nd_flag |= ND_IMPLIEDCLID; nd->nd_clientid.qval = clientid.qval; } - nd->nd_repstat = nfsrv_delegupdate(clientid, NULL, NULL, + nd->nd_repstat = nfsrv_delegupdate(nd, clientid, NULL, NULL, NFSV4OP_DELEGPURGE, nd->nd_cred, p); nfsmout: NFSEXITCODE2(error, nd); @@ -2978,7 +3032,7 @@ nfsrvd_delegreturn(struct nfsrv_descript nd->nd_flag |= ND_IMPLIEDCLID; nd->nd_clientid.qval = clientid.qval; } - nd->nd_repstat = nfsrv_delegupdate(clientid, &stateid, vp, + nd->nd_repstat = nfsrv_delegupdate(nd, clientid, &stateid, vp, NFSV4OP_DELEGRETURN, nd->nd_cred, p); nfsmout: vput(vp); @@ -3016,6 +3070,10 @@ nfsrvd_openconfirm(struct nfsrv_descript nfsv4stateid_t stateid; nfsquad_t clientid; + if ((nd->nd_flag & ND_NFSV41) != 0) { + nd->nd_repstat = NFSERR_NOTSUPP; + goto nfsmout; + } NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID + NFSX_UNSIGNED); stp->ls_ownerlen = 0; stp->ls_op = nd->nd_rp; @@ -3136,6 +3194,10 @@ nfsrvd_renew(struct nfsrv_descript *nd, int error = 0; nfsquad_t clientid; + if ((nd->nd_flag & ND_NFSV41) != 0) { + nd->nd_repstat = NFSERR_NOTSUPP; + goto nfsmout; + } if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) { nd->nd_repstat = NFSERR_WRONGSEC; goto nfsmout; @@ -3151,7 +3213,7 @@ nfsrvd_renew(struct nfsrv_descript *nd, nd->nd_clientid.qval = clientid.qval; } nd->nd_repstat = nfsrv_getclient(clientid, (CLOPS_RENEWOP|CLOPS_RENEW), - NULL, (nfsquad_t)((u_quad_t)0), nd, p); + NULL, NULL, (nfsquad_t)((u_quad_t)0), 0, nd, p); nfsmout: NFSEXITCODE2(error, nd); return (error); @@ -3275,6 +3337,10 @@ nfsrvd_setclientid(struct nfsrv_descript u_char *verf, *ucp, *ucp2, addrbuf[24]; nfsquad_t clientid, confirm; + if ((nd->nd_flag & ND_NFSV41) != 0) { + nd->nd_repstat = NFSERR_NOTSUPP; + goto nfsmout; + } if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) { nd->nd_repstat = NFSERR_WRONGSEC; goto out; @@ -3387,6 +3453,10 @@ nfsrvd_setclientidcfrm(struct nfsrv_desc int error = 0; nfsquad_t clientid, confirm; + if ((nd->nd_flag & ND_NFSV41) != 0) { + nd->nd_repstat = NFSERR_NOTSUPP; + goto nfsmout; + } if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) { nd->nd_repstat = NFSERR_WRONGSEC; goto nfsmout; @@ -3402,7 +3472,7 @@ nfsrvd_setclientidcfrm(struct nfsrv_desc * returns the appropriate NFSERR status. */ nd->nd_repstat = nfsrv_getclient(clientid, (CLOPS_CONFIRM|CLOPS_RENEW), - NULL, confirm, nd, p); + NULL, NULL, confirm, 0, nd, p); nfsmout: NFSEXITCODE2(error, nd); return (error); @@ -3477,6 +3547,10 @@ nfsrvd_releaselckown(struct nfsrv_descri int error = 0, len; nfsquad_t clientid; + if ((nd->nd_flag & ND_NFSV41) != 0) { + nd->nd_repstat = NFSERR_NOTSUPP; + goto nfsmout; + } if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) { nd->nd_repstat = NFSERR_WRONGSEC; goto nfsmout; @@ -3516,3 +3590,383 @@ nfsmout: NFSEXITCODE2(error, nd); return (error); } + +/* + * nfsv4 exchange_id service + */ +APPLESTATIC int +nfsrvd_exchangeid(struct nfsrv_descript *nd, __unused int isdgram, + __unused vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp) +{ + uint32_t *tl; + int error = 0, i, idlen; + struct nfsclient *clp = NULL; + nfsquad_t clientid, confirm; + uint8_t *verf; + uint32_t sp4type, v41flags; + uint64_t owner_minor; + struct timespec verstime; + + if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) { + nd->nd_repstat = NFSERR_WRONGSEC; + goto nfsmout; + } + NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF + NFSX_UNSIGNED); + verf = (uint8_t *)tl; + tl += (NFSX_VERF / NFSX_UNSIGNED); + i = fxdr_unsigned(int, *tl); + if (i > NFSV4_OPAQUELIMIT || i <= 0) { + nd->nd_repstat = NFSERR_BADXDR; + goto nfsmout; + } + idlen = i; + if (nd->nd_flag & ND_GSS) + i += nd->nd_princlen; + clp = (struct nfsclient *)malloc(sizeof(struct nfsclient) + i, + M_NFSDCLIENT, M_WAITOK | M_ZERO); + NFSINITSOCKMUTEX(&clp->lc_req.nr_mtx); + NFSSOCKADDRALLOC(clp->lc_req.nr_nam); + NFSSOCKADDRSIZE(clp->lc_req.nr_nam, sizeof (struct sockaddr_in)); + clp->lc_req.nr_cred = NULL; + NFSBCOPY(verf, clp->lc_verf, NFSX_VERF); + clp->lc_idlen = idlen; + error = nfsrv_mtostr(nd, clp->lc_id, idlen); + if (error != 0) + goto nfsmout; + if ((nd->nd_flag & ND_GSS) != 0) { + clp->lc_flags = LCL_GSS; + if ((nd->nd_flag & ND_GSSINTEGRITY) != 0) + clp->lc_flags |= LCL_GSSINTEGRITY; + else if ((nd->nd_flag & ND_GSSPRIVACY) != 0) + clp->lc_flags |= LCL_GSSPRIVACY; + } else + clp->lc_flags = 0; + if ((nd->nd_flag & ND_GSS) != 0 && nd->nd_princlen > 0) { + clp->lc_flags |= LCL_NAME; + clp->lc_namelen = nd->nd_princlen; + clp->lc_name = &clp->lc_id[idlen]; + NFSBCOPY(nd->nd_principal, clp->lc_name, clp->lc_namelen); + } else { + clp->lc_uid = nd->nd_cred->cr_uid; + clp->lc_gid = nd->nd_cred->cr_gid; + } + NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED); + v41flags = fxdr_unsigned(uint32_t, *tl++); + if ((v41flags & ~(NFSV4EXCH_SUPPMOVEDREFER | NFSV4EXCH_SUPPMOVEDMIGR | + NFSV4EXCH_BINDPRINCSTATEID | NFSV4EXCH_MASKPNFS | + NFSV4EXCH_UPDCONFIRMEDRECA)) != 0) { + nd->nd_repstat = NFSERR_INVAL; + goto nfsmout; + } + if ((v41flags & NFSV4EXCH_UPDCONFIRMEDRECA) != 0) + confirm.lval[1] = 1; + else + confirm.lval[1] = 0; + v41flags = NFSV4EXCH_USENONPNFS; + sp4type = fxdr_unsigned(uint32_t, *tl); + if (sp4type != NFSV4EXCH_SP4NONE) { + nd->nd_repstat = NFSERR_NOTSUPP; + goto nfsmout; + } + + /* + * nfsrv_setclient() does the actual work of adding it to the + * client list. If there is no error, the structure has been + * linked into the client list and clp should no longer be used + * here. When an error is returned, it has not been linked in, + * so it should be free'd. + */ + nd->nd_repstat = nfsrv_setclient(nd, &clp, &clientid, &confirm, p); + if (clp != NULL) { + NFSSOCKADDRFREE(clp->lc_req.nr_nam); + NFSFREEMUTEX(&clp->lc_req.nr_mtx); + free(clp, M_NFSDCLIENT); + } + if (nd->nd_repstat == 0) { + if (confirm.lval[1] != 0) + v41flags |= NFSV4EXCH_CONFIRMEDR; + NFSM_BUILD(tl, uint32_t *, 2 * NFSX_HYPER + 3 * NFSX_UNSIGNED); + *tl++ = clientid.lval[0]; /* ClientID */ + *tl++ = clientid.lval[1]; + *tl++ = txdr_unsigned(confirm.lval[0]); /* SequenceID */ + *tl++ = txdr_unsigned(v41flags); /* Exch flags */ + *tl++ = txdr_unsigned(NFSV4EXCH_SP4NONE); /* No SSV */ + owner_minor = 0; /* Owner */ + txdr_hyper(owner_minor, tl); /* Minor */ + (void)nfsm_strtom(nd, nd->nd_cred->cr_prison->pr_hostuuid, + strlen(nd->nd_cred->cr_prison->pr_hostuuid)); /* Major */ + NFSM_BUILD(tl, uint32_t *, 3 * NFSX_UNSIGNED); + *tl++ = txdr_unsigned(NFSX_UNSIGNED); + NFSBCOPY(&time_uptime, tl++, NFSX_UNSIGNED); + *tl = txdr_unsigned(1); + (void)nfsm_strtom(nd, "freebsd.org", strlen("freebsd.org")); + (void)nfsm_strtom(nd, version, strlen(version)); + NFSM_BUILD(tl, uint32_t *, NFSX_V4TIME); + verstime.tv_sec = 1293840000; /* Jan 1, 2011 */ + verstime.tv_nsec = 0; + txdr_nfsv4time(&verstime, tl); + } + NFSEXITCODE2(0, nd); + return (0); +nfsmout: + if (clp != NULL) { + NFSSOCKADDRFREE(clp->lc_req.nr_nam); + NFSFREEMUTEX(&clp->lc_req.nr_mtx); + free(clp, M_NFSDCLIENT); + } + NFSEXITCODE2(error, nd); + return (error); +} + +/* + * nfsv4 create session service + */ +APPLESTATIC int +nfsrvd_createsession(struct nfsrv_descript *nd, __unused int isdgram, + __unused vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp) +{ + uint32_t *tl; + int error = 0; + nfsquad_t clientid, confirm; + struct nfsdsession *sep = NULL; + uint32_t rdmacnt; + + if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) { + nd->nd_repstat = NFSERR_WRONGSEC; + goto nfsmout; + } + sep = (struct nfsdsession *)malloc(sizeof(struct nfsdsession), + M_NFSDSESSION, M_WAITOK | M_ZERO); + NFSM_DISSECT(tl, uint32_t *, NFSX_HYPER + 2 * NFSX_UNSIGNED); + clientid.lval[0] = *tl++; + clientid.lval[1] = *tl++; + confirm.lval[0] = fxdr_unsigned(uint32_t, *tl++); + sep->sess_crflags = fxdr_unsigned(uint32_t, *tl); + /* Persistent sessions and RDMA are not supported. */ + sep->sess_crflags &= NFSV4CRSESS_CONNBACKCHAN; + + /* Fore channel attributes. */ + NFSM_DISSECT(tl, uint32_t *, 7 * NFSX_UNSIGNED); + tl++; /* Header pad always 0. */ + sep->sess_maxreq = fxdr_unsigned(uint32_t, *tl++); + sep->sess_maxresp = fxdr_unsigned(uint32_t, *tl++); + sep->sess_maxrespcached = fxdr_unsigned(uint32_t, *tl++); + sep->sess_maxops = fxdr_unsigned(uint32_t, *tl++); + sep->sess_maxslots = fxdr_unsigned(uint32_t, *tl++); + if (sep->sess_maxslots > NFSV4_SLOTS) + sep->sess_maxslots = NFSV4_SLOTS; + rdmacnt = fxdr_unsigned(uint32_t, *tl); + if (rdmacnt > 1) { + nd->nd_repstat = NFSERR_BADXDR; + goto nfsmout; + } else if (rdmacnt == 1) + NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED); + + /* Back channel attributes. */ + NFSM_DISSECT(tl, uint32_t *, 7 * NFSX_UNSIGNED); + tl++; /* Header pad always 0. */ + sep->sess_cbmaxreq = fxdr_unsigned(uint32_t, *tl++); + sep->sess_cbmaxresp = fxdr_unsigned(uint32_t, *tl++); + sep->sess_cbmaxrespcached = fxdr_unsigned(uint32_t, *tl++); + sep->sess_cbmaxops = fxdr_unsigned(uint32_t, *tl++); + sep->sess_cbmaxslots = fxdr_unsigned(uint32_t, *tl++); + rdmacnt = fxdr_unsigned(uint32_t, *tl); + if (rdmacnt > 1) { + nd->nd_repstat = NFSERR_BADXDR; + goto nfsmout; + } else if (rdmacnt == 1) + NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED); + + NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED); + sep->sess_cbprogram = fxdr_unsigned(uint32_t, *tl); + + /* + * nfsrv_getclient() searches the client list for a match and + * returns the appropriate NFSERR status. + */ + nd->nd_repstat = nfsrv_getclient(clientid, CLOPS_CONFIRM | CLOPS_RENEW, + NULL, sep, confirm, sep->sess_cbprogram, nd, p); + if (nd->nd_repstat == 0) { + NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID); + NFSBCOPY(sep->sess_sessionid, tl, NFSX_V4SESSIONID); + NFSM_BUILD(tl, uint32_t *, 18 * NFSX_UNSIGNED); + *tl++ = txdr_unsigned(confirm.lval[0]); /* sequenceid */ + *tl++ = txdr_unsigned(sep->sess_crflags); + + /* Fore channel attributes. */ + *tl++ = 0; + *tl++ = txdr_unsigned(sep->sess_maxreq); + *tl++ = txdr_unsigned(sep->sess_maxresp); + *tl++ = txdr_unsigned(sep->sess_maxrespcached); + *tl++ = txdr_unsigned(sep->sess_maxops); + *tl++ = txdr_unsigned(sep->sess_maxslots); + *tl++ = txdr_unsigned(1); + *tl++ = txdr_unsigned(0); /* No RDMA. */ + + /* Back channel attributes. */ + *tl++ = 0; + *tl++ = txdr_unsigned(sep->sess_cbmaxreq); + *tl++ = txdr_unsigned(sep->sess_cbmaxresp); + *tl++ = txdr_unsigned(sep->sess_cbmaxrespcached); + *tl++ = txdr_unsigned(sep->sess_cbmaxops); + *tl++ = txdr_unsigned(sep->sess_cbmaxslots); + *tl++ = txdr_unsigned(1); + *tl = txdr_unsigned(0); /* No RDMA. */ + } +nfsmout: + if (nd->nd_repstat != 0) + free(sep, M_NFSDSESSION); + NFSEXITCODE2(error, nd); + return (error); +} + +/* + * nfsv4 sequence service + */ +APPLESTATIC int +nfsrvd_sequence(struct nfsrv_descript *nd, __unused int isdgram, + __unused vnode_t vp, __unused NFSPROC_T *p, __unused struct nfsexstuff *exp) +{ + uint32_t *tl; + uint32_t highest_slotid, sequenceid, sflags, target_highest_slotid; + int cache_this, error = 0; + + if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) { + nd->nd_repstat = NFSERR_WRONGSEC; + goto nfsmout; + } + NFSM_DISSECT(tl, uint32_t *, NFSX_V4SESSIONID); + NFSBCOPY(tl, nd->nd_sessionid, NFSX_V4SESSIONID); + NFSM_DISSECT(tl, uint32_t *, 4 * NFSX_UNSIGNED); + sequenceid = fxdr_unsigned(uint32_t, *tl++); + nd->nd_slotid = fxdr_unsigned(uint32_t, *tl++); + highest_slotid = fxdr_unsigned(uint32_t, *tl++); + if (*tl == newnfs_true) + cache_this = 1; + else + cache_this = 0; + nd->nd_flag |= ND_HASSEQUENCE; + nd->nd_repstat = nfsrv_checksequence(nd, sequenceid, &highest_slotid, + &target_highest_slotid, cache_this, &sflags, p); + if (nd->nd_repstat == 0) { + NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID); + NFSBCOPY(nd->nd_sessionid, tl, NFSX_V4SESSIONID); + NFSM_BUILD(tl, uint32_t *, 5 * NFSX_UNSIGNED); + *tl++ = txdr_unsigned(sequenceid); + *tl++ = txdr_unsigned(nd->nd_slotid); + *tl++ = txdr_unsigned(highest_slotid); + *tl++ = txdr_unsigned(target_highest_slotid); + *tl = txdr_unsigned(sflags); + } +nfsmout: + NFSEXITCODE2(error, nd); + return (error); +} + +/* + * nfsv4 reclaim complete service + */ +APPLESTATIC int +nfsrvd_reclaimcomplete(struct nfsrv_descript *nd, __unused int isdgram, + __unused vnode_t vp, __unused NFSPROC_T *p, __unused struct nfsexstuff *exp) +{ + uint32_t *tl; + int error = 0; + + if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) { + nd->nd_repstat = NFSERR_WRONGSEC; + goto nfsmout; + } + NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED); + if (*tl == newnfs_true) + nd->nd_repstat = NFSERR_NOTSUPP; + else + nd->nd_repstat = nfsrv_checkreclaimcomplete(nd); +nfsmout: + NFSEXITCODE2(error, nd); + return (error); +} + +/* + * nfsv4 destroy clientid service + */ +APPLESTATIC int +nfsrvd_destroyclientid(struct nfsrv_descript *nd, __unused int isdgram, + __unused vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp) +{ + uint32_t *tl; + nfsquad_t clientid; + int error = 0; + + if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) { + nd->nd_repstat = NFSERR_WRONGSEC; + goto nfsmout; + } + NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED); + clientid.lval[0] = *tl++; + clientid.lval[1] = *tl; + nd->nd_repstat = nfsrv_destroyclient(clientid, p); +nfsmout: + NFSEXITCODE2(error, nd); + return (error); +} + +/* + * nfsv4 destroy session service + */ +APPLESTATIC int +nfsrvd_destroysession(struct nfsrv_descript *nd, __unused int isdgram, + __unused vnode_t vp, __unused NFSPROC_T *p, __unused struct nfsexstuff *exp) +{ + uint8_t *cp, sessid[NFSX_V4SESSIONID]; + int error = 0; + + if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) { + nd->nd_repstat = NFSERR_WRONGSEC; + goto nfsmout; + } + NFSM_DISSECT(cp, uint8_t *, NFSX_V4SESSIONID); + NFSBCOPY(cp, sessid, NFSX_V4SESSIONID); + nd->nd_repstat = nfsrv_destroysession(nd, sessid); +nfsmout: + NFSEXITCODE2(error, nd); + return (error); +} + +/* + * nfsv4 free stateid service + */ +APPLESTATIC int +nfsrvd_freestateid(struct nfsrv_descript *nd, __unused int isdgram, + __unused vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp) +{ + uint32_t *tl; + nfsv4stateid_t stateid; + int error = 0; + + if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) { + nd->nd_repstat = NFSERR_WRONGSEC; + goto nfsmout; + } + NFSM_DISSECT(tl, uint32_t *, NFSX_STATEID); + stateid.seqid = fxdr_unsigned(uint32_t, *tl++); + NFSBCOPY(tl, stateid.other, NFSX_STATEIDOTHER); + nd->nd_repstat = nfsrv_freestateid(nd, &stateid, p); +nfsmout: + NFSEXITCODE2(error, nd); + return (error); +} + +/* + * nfsv4 service not supported + */ +APPLESTATIC int +nfsrvd_notsupp(struct nfsrv_descript *nd, __unused int isdgram, + __unused vnode_t vp, __unused NFSPROC_T *p, __unused struct nfsexstuff *exp) +{ + + nd->nd_repstat = NFSERR_NOTSUPP; + NFSEXITCODE2(0, nd); + return (0); +} +help
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201307160005.r6G05H7L001796>
