Date: Tue, 16 Jul 2013 23:29:25 +0000 (UTC) From: Rick Macklem <rmacklem@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r253401 - projects/nfsv4.1-server/sys/fs/nfsserver Message-ID: <201307162329.r6GNTPIM038904@svn.freebsd.org>
index | next in thread | raw e-mail
Author: rmacklem Date: Tue Jul 16 23:29:24 2013 New Revision: 253401 URL: http://svnweb.freebsd.org/changeset/base/253401 Log: Merge in the NFSv4.1 server code for 2 more files. Modified: projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdsocket.c projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdsubs.c Modified: projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdsocket.c ============================================================================== --- projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdsocket.c Tue Jul 16 23:19:05 2013 (r253400) +++ projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdsocket.c Tue Jul 16 23:29:24 2013 (r253401) @@ -48,6 +48,7 @@ extern struct nfsv4lock nfsv4rootfs_lock extern struct nfsrv_stablefirst nfsrv_stablefirst; extern struct nfsclienthashhead nfsclienthash[NFSCLIENTHASHSIZE]; extern int nfsrc_floodlevel, nfsrc_tcpsavedreplies; +extern int nfsd_debuglevel; NFSV4ROOTLOCKMUTEX; NFSSTATESPINLOCK; @@ -131,7 +132,7 @@ int (*nfsrv3_procs2[NFS_V3NPROCS])(struc (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, }; -int (*nfsrv4_ops0[NFSV4OP_NOPS])(struct nfsrv_descript *, +int (*nfsrv4_ops0[NFSV41_NOPS])(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *) = { (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, @@ -173,9 +174,28 @@ int (*nfsrv4_ops0[NFSV4OP_NOPS])(struct nfsrvd_verify, nfsrvd_write, nfsrvd_releaselckown, + nfsrvd_notsupp, + nfsrvd_notsupp, + nfsrvd_exchangeid, + nfsrvd_createsession, + nfsrvd_destroysession, + nfsrvd_freestateid, + nfsrvd_notsupp, + nfsrvd_notsupp, + nfsrvd_notsupp, + nfsrvd_notsupp, + nfsrvd_notsupp, + nfsrvd_notsupp, + nfsrvd_notsupp, + nfsrvd_sequence, + nfsrvd_notsupp, + nfsrvd_notsupp, + nfsrvd_notsupp, + nfsrvd_destroyclientid, + nfsrvd_reclaimcomplete, }; -int (*nfsrv4_ops1[NFSV4OP_NOPS])(struct nfsrv_descript *, +int (*nfsrv4_ops1[NFSV41_NOPS])(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *) = { (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, @@ -218,9 +238,28 @@ int (*nfsrv4_ops1[NFSV4OP_NOPS])(struct (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, + (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, + (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, + (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, + (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, + (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, + (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, + (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, + (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, + (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, + (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, + (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, + (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, + (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, + (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, + (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, + (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, + (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, + (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, + (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, }; -int (*nfsrv4_ops2[NFSV4OP_NOPS])(struct nfsrv_descript *, +int (*nfsrv4_ops2[NFSV41_NOPS])(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *) = { (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, @@ -263,6 +302,25 @@ int (*nfsrv4_ops2[NFSV4OP_NOPS])(struct (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, + (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, + (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, + (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, + (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, + (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, + (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, + (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, + (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, + (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, + (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, + (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, + (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, + (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, + (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, + (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, + (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, + (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, + (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, + (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, }; #endif /* !APPLEKEXT */ @@ -304,7 +362,7 @@ static int nfs_writerpc[NFS_NPROCS] = { /* local functions */ static void nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, - NFSPROC_T *p); + u_char *tag, int taglen, u_int32_t minorvers, NFSPROC_T *p); /* @@ -314,7 +372,7 @@ static void nfsrvd_compound(struct nfsrv static int nfs_retfh[NFS_V3NPROCS] = { 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0 }; -extern struct nfsv4_opflag nfsv4_opflag[NFSV4OP_NOPS]; +extern struct nfsv4_opflag nfsv4_opflag[NFSV41_NOPS]; static int nfsv3to4op[NFS_V3NPROCS] = { NFSPROC_NULL, @@ -349,8 +407,8 @@ static int nfsv3to4op[NFS_V3NPROCS] = { * The NFS V4 Compound RPC is performed separately by nfsrvd_compound(). */ APPLESTATIC void -nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram, - NFSPROC_T *p) +nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram, u_char *tag, int taglen, + u_int32_t minorvers, NFSPROC_T *p) { int error = 0, lktype; vnode_t vp; @@ -427,7 +485,7 @@ nfsrvd_dorpc(struct nfsrv_descript *nd, * The group is indicated by the value in nfs_retfh[]. */ if (nd->nd_flag & ND_NFSV4) { - nfsrvd_compound(nd, isdgram, p); + nfsrvd_compound(nd, isdgram, tag, taglen, minorvers, p); } else { if (nfs_retfh[nd->nd_procnum] == 1) { if (vp) @@ -482,15 +540,14 @@ out: * vnode pointer handling. */ static void -nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, - NFSPROC_T *p) +nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag, + int taglen, u_int32_t minorvers, NFSPROC_T *p) { - int i, op; + int i, op, op0 = 0; u_int32_t *tl; struct nfsclient *clp, *nclp; - int numops, taglen = -1, error = 0, igotlock; - u_int32_t minorvers, retops = 0, *retopsp = NULL, *repp; - u_char tag[NFSV4_SMALLSTR + 1], *tagstr; + int numops, error = 0, igotlock; + u_int32_t retops = 0, *retopsp = NULL, *repp; vnode_t vp, nvp, savevp; struct nfsrvfh fh; mount_t new_mp, temp_mp = NULL; @@ -595,31 +652,17 @@ nfsrvd_compound(struct nfsrv_descript *n savevp = vp = NULL; save_fsid.val[0] = save_fsid.val[1] = 0; cur_fsid.val[0] = cur_fsid.val[1] = 0; - NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); - taglen = fxdr_unsigned(int, *tl); + + /* If taglen < 0, there was a parsing error in nfsd_getminorvers(). */ if (taglen < 0) { error = EBADRPC; goto nfsmout; } - if (taglen <= NFSV4_SMALLSTR) - tagstr = tag; - else - tagstr = malloc(taglen + 1, M_TEMP, M_WAITOK); - error = nfsrv_mtostr(nd, tagstr, taglen); - if (error) { - if (taglen > NFSV4_SMALLSTR) - free(tagstr, M_TEMP); - taglen = -1; - goto nfsmout; - } + (void) nfsm_strtom(nd, tag, taglen); - if (taglen > NFSV4_SMALLSTR) { - free(tagstr, M_TEMP); - } NFSM_BUILD(retopsp, u_int32_t *, NFSX_UNSIGNED); - NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED); - minorvers = fxdr_unsigned(u_int32_t, *tl++); - if (minorvers != NFSV4_MINORVERSION) + NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); + if (minorvers != NFSV4_MINORVERSION && minorvers != NFSV41_MINORVERSION) nd->nd_repstat = NFSERR_MINORVERMISMATCH; if (nd->nd_repstat) numops = 0; @@ -638,7 +681,10 @@ nfsrvd_compound(struct nfsrv_descript *n NFSM_BUILD(repp, u_int32_t *, 2 * NFSX_UNSIGNED); *repp = *tl; op = fxdr_unsigned(int, *tl); - if (op < NFSV4OP_ACCESS || op >= NFSV4OP_NOPS) { + NFSD_DEBUG(4, "op=%d\n", op); + if (op < NFSV4OP_ACCESS || + (op >= NFSV4OP_NOPS && (nd->nd_flag & ND_NFSV41) == 0) || + (op >= NFSV41_NOPS && (nd->nd_flag & ND_NFSV41) != 0)) { nd->nd_repstat = NFSERR_OPILLEGAL; *repp++ = txdr_unsigned(NFSV4OP_OPILLEGAL); *repp = nfsd_errmap(nd); @@ -647,6 +693,10 @@ nfsrvd_compound(struct nfsrv_descript *n } else { repp++; } + if (i == 0) + op0 = op; + if (i == numops - 1) + nd->nd_flag |= ND_LASTOP; /* * Check for a referral on the current FH and, if so, return @@ -661,6 +711,29 @@ nfsrvd_compound(struct nfsrv_descript *n break; } + /* + * For NFSv4.1, check for a Sequence Operation being first + * or one of the other allowed operations by itself. + */ + if ((nd->nd_flag & ND_NFSV41) != 0) { + if (i != 0 && op == NFSV4OP_SEQUENCE) + nd->nd_repstat = NFSERR_SEQUENCEPOS; + else if (i == 0 && op != NFSV4OP_SEQUENCE && + op != NFSV4OP_EXCHANGEID && + op != NFSV4OP_CREATESESSION && + op != NFSV4OP_BINDCONNTOSESS && + op != NFSV4OP_DESTROYCLIENTID && + op != NFSV4OP_DESTROYSESSION) + nd->nd_repstat = NFSERR_OPNOTINSESS; + else if (i != 0 && op0 != NFSV4OP_SEQUENCE) + nd->nd_repstat = NFSERR_NOTONLYOP; + if (nd->nd_repstat != 0) { + *repp = nfsd_errmap(nd); + retops++; + break; + } + } + nd->nd_procnum = op; /* * If over flood level, reply NFSERR_RESOURCE, if at the first @@ -672,7 +745,8 @@ nfsrvd_compound(struct nfsrv_descript *n * If nfsrv_mallocmget_limit() returns True, the system is near * to its limit for memory that malloc()/mget() can allocate. */ - if (i == 0 && nd->nd_rp->rc_refcnt == 0 && + if (i == 0 && (nd->nd_rp == NULL || + nd->nd_rp->rc_refcnt == 0) && (nfsrv_mallocmget_limit() || nfsrc_tcpsavedreplies > nfsrc_floodlevel)) { if (nfsrc_tcpsavedreplies > nfsrc_floodlevel) { Modified: projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdsubs.c ============================================================================== --- projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdsubs.c Tue Jul 16 23:19:05 2013 (r253400) +++ projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdsubs.c Tue Jul 16 23:29:24 2013 (r253401) @@ -46,6 +46,7 @@ extern u_int32_t newnfs_true, newnfs_fal extern int nfs_pubfhset; extern struct nfsclienthashhead nfsclienthash[NFSCLIENTHASHSIZE]; extern struct nfslockhashhead nfslockhash[NFSLOCKHASHSIZE]; +extern struct nfssessionhash nfssessionhash[NFSSESSIONHASHSIZE]; extern int nfsrv_useacl; extern uid_t nfsrv_defaultuid; extern gid_t nfsrv_defaultgid; @@ -56,6 +57,8 @@ static nfstype newnfsv2_type[9] = { NFNO extern nfstype nfsv34_type[9]; #endif /* !APPLEKEXT */ +static u_int32_t nfsrv_isannfserr(u_int32_t); + SYSCTL_DECL(_vfs_nfsd); static int disable_checkutf8 = 0; @@ -68,16 +71,16 @@ static char nfsrv_hexdigit(char, int *); /* * Maps errno values to nfs error numbers. * Use NFSERR_IO as the catch all for ones not specifically defined in - * RFC 1094. + * RFC 1094. (It now includes the errors added for NFSv3.) */ -static u_char nfsrv_v2errmap[ELAST] = { +static u_char nfsrv_v2errmap[NFSERR_REMOTE] = { NFSERR_PERM, NFSERR_NOENT, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_NXIO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_ACCES, NFSERR_IO, NFSERR_IO, - NFSERR_IO, NFSERR_EXIST, NFSERR_IO, NFSERR_NODEV, NFSERR_NOTDIR, - NFSERR_ISDIR, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, + NFSERR_IO, NFSERR_EXIST, NFSERR_XDEV, NFSERR_NODEV, NFSERR_NOTDIR, + NFSERR_ISDIR, NFSERR_INVAL, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_FBIG, NFSERR_NOSPC, NFSERR_IO, NFSERR_ROFS, - NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, + NFSERR_MLINK, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, @@ -85,9 +88,7 @@ static u_char nfsrv_v2errmap[ELAST] = { NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_NAMETOL, NFSERR_IO, NFSERR_IO, NFSERR_NOTEMPTY, NFSERR_IO, NFSERR_IO, NFSERR_DQUOT, NFSERR_STALE, - NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, - NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, - NFSERR_IO, + NFSERR_REMOTE, }; /* @@ -1493,19 +1494,41 @@ nfsd_errmap(struct nfsrv_descript *nd) else if (nd->nd_repstat == NFSERR_MINORVERMISMATCH || nd->nd_repstat == NFSERR_OPILLEGAL) return (txdr_unsigned(nd->nd_repstat)); - else + else if ((nd->nd_flag & ND_NFSV41) != 0) { + if (nd->nd_repstat == EOPNOTSUPP) + nd->nd_repstat = NFSERR_NOTSUPP; + nd->nd_repstat = nfsrv_isannfserr(nd->nd_repstat); + return (txdr_unsigned(nd->nd_repstat)); + } else errp = defaulterrp = nfsrv_v4errmap[nd->nd_procnum]; while (*++errp) if (*errp == nd->nd_repstat) return (txdr_unsigned(nd->nd_repstat)); return (txdr_unsigned(*defaulterrp)); } - if (nd->nd_repstat <= ELAST) + if (nd->nd_repstat <= NFSERR_REMOTE) return (txdr_unsigned(nfsrv_v2errmap[nd->nd_repstat - 1])); return (txdr_unsigned(NFSERR_IO)); } /* + * Check to see if the error is a valid NFS one. If not, replace it with + * NFSERR_IO. + */ +static u_int32_t +nfsrv_isannfserr(u_int32_t errval) +{ + + if (errval == NFSERR_OK) + return (errval); + if (errval >= NFSERR_BADHANDLE && errval <= NFSERR_DELEGREVOKED) + return (errval); + if (errval > 0 && errval <= NFSERR_REMOTE) + return (nfsrv_v2errmap[errval - 1]); + return (NFSERR_IO); +} + +/* * Check to see if setting a uid/gid is permitted when creating a new * file object. (Called when uid and/or gid is specified in the * settable attributes for V4. @@ -2046,6 +2069,8 @@ nfsd_init(void) LIST_INIT(&nfsclienthash[i]); for (i = 0; i < NFSLOCKHASHSIZE; i++) LIST_INIT(&nfslockhash[i]); + for (i = 0; i < NFSSESSIONHASHSIZE; i++) + LIST_INIT(&nfssessionhash[i].list); /* and the v2 pubfh should be all zeros */ NFSBZERO(nfs_v2pubfh, NFSX_V2FH); @@ -2073,3 +2098,42 @@ nfsd_checkrootexp(struct nfsrv_descript return (1); } +/* + * Parse the first part of an NFSv4 compound to find out what the minor + * version# is. + */ +void +nfsd_getminorvers(struct nfsrv_descript *nd, u_char *tag, u_char **tagstrp, + int *taglenp, u_int32_t *minversp) +{ + uint32_t *tl; + int error = 0, taglen = -1; + u_char *tagstr = NULL; + + NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED); + taglen = fxdr_unsigned(int, *tl); + if (taglen < 0 || taglen > NFSV4_OPAQUELIMIT) { + error = EBADRPC; + goto nfsmout; + } + if (taglen <= NFSV4_SMALLSTR) + tagstr = tag; + else + tagstr = malloc(taglen + 1, M_TEMP, M_WAITOK); + error = nfsrv_mtostr(nd, tagstr, taglen); + if (error != 0) + goto nfsmout; + NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED); + *minversp = fxdr_unsigned(u_int32_t, *tl); + *tagstrp = tagstr; + if (*minversp == NFSV41_MINORVERSION) + nd->nd_flag |= ND_NFSV41; +nfsmout: + if (error != 0) { + if (tagstr != NULL && taglen > NFSV4_SMALLSTR) + free(tagstr, M_TEMP); + taglen = -1; + } + *taglenp = taglen; +} +help
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201307162329.r6GNTPIM038904>
