Merge WebNFS changes from NetBSD.

Obtained from:	NetBSD
This commit is contained in:
Doug Rabson 1997-07-16 09:06:30 +00:00
parent 5827e97390
commit e775608178
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=27446
20 changed files with 1151 additions and 258 deletions

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs.h 8.4 (Berkeley) 5/1/95
* $Id: nfs.h,v 1.27 1997/05/19 14:36:46 dfr Exp $
* $Id: nfs.h,v 1.28 1997/06/03 17:22:45 dfr Exp $
*/
#ifndef _NFS_NFS_H_
@ -522,6 +522,30 @@ extern int nfsd_head_flag;
!bcmp((caddr_t)&(o)->nd_cr, (caddr_t)&(n)->nd_cr, \
sizeof (struct ucred)))
/*
* Defines for WebNFS
*/
#define WEBNFS_ESC_CHAR '%'
#define WEBNFS_SPECCHAR_START 0x80
#define WEBNFS_NATIVE_CHAR 0x80
/*
* ..
* Possibly more here in the future.
*/
/*
* Macro for converting escape characters in WebNFS pathnames.
* Should really be in libkern.
*/
#define HEXTOC(c) \
((c) >= 'a' ? ((c) - ('a' - 10)) : \
((c) >= 'A' ? ((c) - ('A' - 10)) : ((c) - '0')))
#define HEXSTRTOI(p) \
((HEXTOC(p[0]) << 4) + HEXTOC(p[1]))
#ifdef NFS_DEBUG
extern int nfs_debug;
@ -564,7 +588,7 @@ void nfsm_srvpostopattr __P((struct nfsrv_descript *,int,struct vattr *,struct m
int netaddr_match __P((int,union nethostaddr *,struct mbuf *));
int nfs_request __P((struct vnode *,struct mbuf *,int,struct proc *,struct ucred *,struct mbuf **,struct mbuf **,caddr_t *));
int nfs_loadattrcache __P((struct vnode **,struct mbuf **,caddr_t *,struct vattr *));
int nfs_namei __P((struct nameidata *,fhandle_t *,int,struct nfssvc_sock *,struct mbuf *,struct mbuf **,caddr_t *,struct vnode **,struct proc *,int));
int nfs_namei __P((struct nameidata *,fhandle_t *,int,struct nfssvc_sock *,struct mbuf *,struct mbuf **,caddr_t *,struct vnode **,struct proc *,int,int));
void nfsm_adj __P((struct mbuf *,int,int));
int nfsm_mbuftouio __P((struct mbuf **,struct uio *,int,caddr_t *));
void nfsrv_initcache __P((void));
@ -606,7 +630,10 @@ int nfsrv_create __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
struct proc *procp, struct mbuf **mrq));
int nfsrv_fhtovp __P((fhandle_t *,int,struct vnode **,
struct ucred *,struct nfssvc_sock *,struct mbuf *,
int *,int));
int *,int,int));
int nfsrv_setpublicfs __P((struct mount *, struct netexport *,
struct export_args *));
int nfs_ispublicfh __P((fhandle_t *));
int nfsrv_fsinfo __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
struct proc *procp, struct mbuf **mrq));
int nfsrv_getattr __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_subs.c 8.3 (Berkeley) 1/4/94
* $Id: nfs_subs.c,v 1.37 1997/02/22 09:42:41 peter Exp $
* $Id: nfs_subs.c,v 1.38 1997/04/04 17:49:29 dfr Exp $
*/
/*
@ -53,6 +53,7 @@
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/malloc.h>
#include <sys/dirent.h>
#ifdef VFS_LKM
#include <sys/sysent.h>
#include <sys/syscall.h>
@ -560,6 +561,8 @@ extern int nfssvc(struct proc *, struct nfssvc_args *, int *);
LIST_HEAD(nfsnodehashhead, nfsnode);
int nfs_webnamei __P((struct nameidata *, struct vnode *, struct proc *));
/*
* Create the header for an rpc request packet
* The hsiz is the size of the rest of the nfs request header.
@ -1412,10 +1415,16 @@ nfs_getattrcache(vp, vaper)
#ifndef NFS_NOSERVER
/*
* Set up nameidata for a lookup() call and do it
* Set up nameidata for a lookup() call and do it.
*
* If pubflag is set, this call is done for a lookup operation on the
* public filehandle. In that case we allow crossing mountpoints and
* absolute pathnames. However, the caller is expected to check that
* the lookup result is within the public fs, and deny access if
* it is not.
*/
int
nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, retdirp, p, kerbflag)
nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, retdirp, p, kerbflag, pubflag)
register struct nameidata *ndp;
fhandle_t *fhp;
int len;
@ -1425,13 +1434,15 @@ nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, retdirp, p, kerbflag)
caddr_t *dposp;
struct vnode **retdirp;
struct proc *p;
int kerbflag;
int kerbflag, pubflag;
{
register int i, rem;
register struct mbuf *md;
register char *fromcp, *tocp;
register char *fromcp, *tocp, *cp;
struct iovec aiov;
struct uio auio;
struct vnode *dp;
int error, rdonly;
int error, rdonly, linklen;
struct componentname *cnp = &ndp->ni_cnd;
*retdirp = (struct vnode *)0;
@ -1455,7 +1466,7 @@ nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, retdirp, p, kerbflag)
fromcp = mtod(md, caddr_t);
rem = md->m_len;
}
if (*fromcp == '\0' || *fromcp == '/') {
if (*fromcp == '\0' || (!pubflag && *fromcp == '/')) {
error = EACCES;
goto out;
}
@ -1473,55 +1484,170 @@ nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, retdirp, p, kerbflag)
else if (error = nfs_adv(mdp, dposp, len, rem))
goto out;
}
ndp->ni_pathlen = tocp - cnp->cn_pnbuf;
cnp->cn_nameptr = cnp->cn_pnbuf;
/*
* Extract and set starting directory.
*/
if (error = nfsrv_fhtovp(fhp, FALSE, &dp, ndp->ni_cnd.cn_cred, slp,
nam, &rdonly, kerbflag))
error = nfsrv_fhtovp(fhp, FALSE, &dp, ndp->ni_cnd.cn_cred, slp,
nam, &rdonly, kerbflag, pubflag);
if (error)
goto out;
if (dp->v_type != VDIR) {
vrele(dp);
error = ENOTDIR;
goto out;
}
VREF(dp);
*retdirp = dp;
ndp->ni_startdir = dp;
if (rdonly)
cnp->cn_flags |= (NOCROSSMOUNT | RDONLY);
else
cnp->cn_flags |= NOCROSSMOUNT;
cnp->cn_flags |= RDONLY;
if (pubflag) {
/*
* Oh joy. For WebNFS, handle those pesky '%' escapes,
* and the 'native path' indicator.
*/
MALLOC(cp, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
fromcp = cnp->cn_pnbuf;
tocp = cp;
if ((unsigned char)*fromcp >= WEBNFS_SPECCHAR_START) {
switch ((unsigned char)*fromcp) {
case WEBNFS_NATIVE_CHAR:
/*
* 'Native' path for us is the same
* as a path according to the NFS spec,
* just skip the escape char.
*/
fromcp++;
break;
/*
* More may be added in the future, range 0x80-0xff
*/
default:
error = EIO;
FREE(cp, M_NAMEI);
goto out;
}
}
/*
* Translate the '%' escapes, URL-style.
*/
while (*fromcp != '\0') {
if (*fromcp == WEBNFS_ESC_CHAR) {
if (fromcp[1] != '\0' && fromcp[2] != '\0') {
fromcp++;
*tocp++ = HEXSTRTOI(fromcp);
fromcp += 2;
continue;
} else {
error = ENOENT;
FREE(cp, M_NAMEI);
goto out;
}
} else
*tocp++ = *fromcp++;
}
*tocp = '\0';
FREE(cnp->cn_pnbuf, M_NAMEI);
cnp->cn_pnbuf = cp;
}
ndp->ni_pathlen = (tocp - cnp->cn_pnbuf) + 1;
ndp->ni_segflg = UIO_SYSSPACE;
if (pubflag) {
ndp->ni_rootdir = rootvnode;
ndp->ni_loopcnt = 0;
if (cnp->cn_pnbuf[0] == '/')
dp = rootvnode;
} else {
cnp->cn_flags |= NOCROSSMOUNT;
}
cnp->cn_proc = p;
VREF(dp);
for (;;) {
cnp->cn_nameptr = cnp->cn_pnbuf;
ndp->ni_startdir = dp;
/*
* And call lookup() to do the real work
*/
cnp->cn_proc = p;
if (error = lookup(ndp))
goto out;
break;
/*
* Check for encountering a symbolic link
*/
if (cnp->cn_flags & ISSYMLINK) {
if ((cnp->cn_flags & ISSYMLINK) == 0) {
nfsrv_object_create(ndp->ni_vp);
if (cnp->cn_flags & (SAVENAME | SAVESTART)) {
cnp->cn_flags |= HASBUF;
return (0);
}
break;
} else {
if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1)
vput(ndp->ni_dvp);
else
VOP_UNLOCK(ndp->ni_dvp, 0, p);
if (!pubflag) {
vrele(ndp->ni_dvp);
vput(ndp->ni_vp);
ndp->ni_vp = NULL;
error = EINVAL;
break;
}
if (ndp->ni_loopcnt++ >= MAXSYMLINKS) {
error = ELOOP;
break;
}
if (ndp->ni_pathlen > 0)
MALLOC(cp, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
else
cp = cnp->cn_pnbuf;
aiov.iov_base = cp;
aiov.iov_len = MAXPATHLEN;
auio.uio_iov = &aiov;
auio.uio_iovcnt = 1;
auio.uio_offset = 0;
auio.uio_rw = UIO_READ;
auio.uio_segflg = UIO_SYSSPACE;
auio.uio_procp = (struct proc *)0;
auio.uio_resid = MAXPATHLEN;
error = VOP_READLINK(ndp->ni_vp, &auio, cnp->cn_cred);
if (error) {
badlink:
if (ndp->ni_pathlen > 1)
FREE(cp, M_NAMEI);
break;
}
linklen = MAXPATHLEN - auio.uio_resid;
if (linklen == 0) {
error = ENOENT;
goto badlink;
}
if (linklen + ndp->ni_pathlen >= MAXPATHLEN) {
error = ENAMETOOLONG;
goto badlink;
}
if (ndp->ni_pathlen > 1) {
bcopy(ndp->ni_next, cp + linklen, ndp->ni_pathlen);
FREE(cnp->cn_pnbuf, M_NAMEI);
cnp->cn_pnbuf = cp;
} else
cnp->cn_pnbuf[linklen] = '\0';
ndp->ni_pathlen += linklen;
vput(ndp->ni_vp);
ndp->ni_vp = NULL;
error = EINVAL;
goto out;
}
nfsrv_object_create(ndp->ni_vp);
/*
* Check for saved name request
*/
if (cnp->cn_flags & (SAVENAME | SAVESTART)) {
cnp->cn_flags |= HASBUF;
return (0);
dp = ndp->ni_dvp;
/*
* Check if root directory should replace current directory.
*/
if (cnp->cn_pnbuf[0] == '/') {
vrele(dp);
dp = ndp->ni_rootdir;
VREF(dp);
}
}
}
out:
FREE(cnp->cn_pnbuf, M_NAMEI);
return (error);
@ -1700,7 +1826,7 @@ nfsm_srvfattr(nfsd, vap, fp)
* - if not lockflag unlock it with VOP_UNLOCK()
*/
int
nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag)
nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag, pubflag)
fhandle_t *fhp;
int lockflag;
struct vnode **vpp;
@ -1709,6 +1835,7 @@ nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag)
struct mbuf *nam;
int *rdonlyp;
int kerbflag;
int pubflag;
{
struct proc *p = curproc; /* XXX */
register struct mount *mp;
@ -1717,6 +1844,13 @@ nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag)
int error, exflags;
*vpp = (struct vnode *)0;
if (nfs_ispublicfh(fhp)) {
if (!pubflag || !nfs_pub.np_valid)
return (ESTALE);
fhp = &nfs_pub.np_handle;
}
mp = vfs_getvfs(&fhp->fh_fsid);
if (!mp)
return (ESTALE);
@ -1752,6 +1886,25 @@ nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag)
return (0);
}
/*
* WebNFS: check if a filehandle is a public filehandle. For v3, this
* means a length of 0, for v2 it means all zeroes. nfsm_srvmtofh has
* transformed this to all zeroes in both cases, so check for it.
*/
int
nfs_ispublicfh(fhp)
fhandle_t *fhp;
{
char *cp = (char *)fhp;
int i;
for (i = 0; i < NFSX_V3FH; i++)
if (*cp++ != 0)
return (FALSE);
return (TRUE);
}
#endif /* NFS_NOSERVER */
/*
* This function compares two net addresses by family and returns TRUE

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfsm_subs.h 8.2 (Berkeley) 3/30/95
* $Id$
* $Id: nfsm_subs.h,v 1.12 1997/02/22 09:42:48 peter Exp $
*/
@ -363,18 +363,24 @@ struct mbuf *nfsm_rpchead __P((struct ucred *cr, int nmflag, int procid,
} }
#define nfsm_srvmtofh(f) \
{ if (nfsd->nd_flag & ND_NFSV3) { \
{ int fhlen = NFSX_V3FH; \
if (nfsd->nd_flag & ND_NFSV3) { \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
if (fxdr_unsigned(int, *tl) != NFSX_V3FH) { \
fhlen = fxdr_unsigned(int, *tl); \
if (fhlen == 0) { \
bzero((caddr_t)(f), NFSX_V3FH); \
} else if (fhlen != NFSX_V3FH) { \
error = EBADRPC; \
nfsm_reply(0); \
} \
} \
nfsm_dissect(tl, u_long *, NFSX_V3FH); \
bcopy((caddr_t)tl, (caddr_t)(f), NFSX_V3FH); \
if ((nfsd->nd_flag & ND_NFSV3) == 0) \
nfsm_adv(NFSX_V2FH - NFSX_V3FH); \
}
if (fhlen != 0) { \
nfsm_dissect(tl, u_long *, NFSX_V3FH); \
bcopy((caddr_t)tl, (caddr_t)(f), NFSX_V3FH); \
if ((nfsd->nd_flag & ND_NFSV3) == 0) \
nfsm_adv(NFSX_V2FH - NFSX_V3FH); \
} \
}
#define nfsm_clget \
if (bp >= be) { \

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_nqlease.c 8.9 (Berkeley) 5/20/95
* $Id: nfs_nqlease.c,v 1.24 1997/02/22 09:42:37 peter Exp $
* $Id: nfs_nqlease.c,v 1.25 1997/06/03 17:22:46 dfr Exp $
*/
@ -751,7 +751,7 @@ nqnfsrv_getlease(nfsd, slp, procp, mrq)
flags = fxdr_unsigned(int, *tl++);
nfsd->nd_duration = fxdr_unsigned(int, *tl);
error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly,
(nfsd->nd_flag & ND_KERBAUTH));
(nfsd->nd_flag & ND_KERBAUTH), TRUE);
if (error)
nfsm_reply(0);
if (rdonly && flags == ND_WRITE) {

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_serv.c 8.3 (Berkeley) 1/12/94
* $Id: nfs_serv.c,v 1.43 1997/06/03 13:56:54 dfr Exp $
* $Id: nfs_serv.c,v 1.44 1997/06/14 11:19:35 bde Exp $
*/
/*
@ -140,7 +140,7 @@ nfsrv3_access(nfsd, slp, procp, mrq)
nfsm_srvmtofh(fhp);
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
if (error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
&rdonly, (nfsd->nd_flag & ND_KERBAUTH))) {
&rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE)) {
nfsm_reply(NFSX_UNSIGNED);
nfsm_srvpostop_attr(1, (struct vattr *)0);
return (0);
@ -204,7 +204,7 @@ nfsrv_getattr(nfsd, slp, procp, mrq)
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
if (error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
&rdonly, (nfsd->nd_flag & ND_KERBAUTH))) {
&rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE)) {
nfsm_reply(0);
return (0);
}
@ -296,7 +296,7 @@ nfsrv_setattr(nfsd, slp, procp, mrq)
* Now that we have all the fields, lets do it.
*/
if (error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
&rdonly, (nfsd->nd_flag & ND_KERBAUTH))) {
&rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE)) {
nfsm_reply(2 * NFSX_UNSIGNED);
nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap);
return (0);
@ -365,7 +365,7 @@ nfsrv_lookup(nfsd, slp, procp, mrq)
caddr_t dpos = nfsd->nd_dpos;
struct ucred *cred = &nfsd->nd_cr;
register struct nfs_fattr *fp;
struct nameidata nd;
struct nameidata nd, ind, *ndp = &nd;
struct vnode *vp, *dirp;
nfsfh_t nfh;
fhandle_t *fhp;
@ -374,7 +374,7 @@ nfsrv_lookup(nfsd, slp, procp, mrq)
register long t1;
caddr_t bpos;
int error = 0, cache, len, dirattr_ret = 1;
int v3 = (nfsd->nd_flag & ND_NFSV3);
int v3 = (nfsd->nd_flag & ND_NFSV3), pubflag;
char *cp2;
struct mbuf *mb, *mb2, *mreq;
struct vattr va, dirattr, *vap = &va;
@ -383,26 +383,72 @@ nfsrv_lookup(nfsd, slp, procp, mrq)
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
nfsm_srvnamesiz(len);
pubflag = nfs_ispublicfh(fhp);
nd.ni_cnd.cn_cred = cred;
nd.ni_cnd.cn_nameiop = LOOKUP;
nd.ni_cnd.cn_flags = LOCKLEAF | SAVESTART;
error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
&dirp, procp, (nfsd->nd_flag & ND_KERBAUTH));
&dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), pubflag);
if (!error && pubflag) {
if (nd.ni_vp->v_type == VDIR && nfs_pub.np_index != NULL) {
/*
* Setup call to lookup() to see if we can find
* the index file. Arguably, this doesn't belong
* in a kernel.. Ugh.
*/
ind = nd;
VOP_UNLOCK(nd.ni_vp, 0, procp);
ind.ni_pathlen = strlen(nfs_pub.np_index);
ind.ni_cnd.cn_nameptr = ind.ni_cnd.cn_pnbuf =
nfs_pub.np_index;
ind.ni_startdir = nd.ni_vp;
VREF(ind.ni_startdir);
error = lookup(&ind);
if (!error) {
/*
* Found an index file. Get rid of
* the old references.
*/
if (dirp)
vrele(dirp);
dirp = nd.ni_vp;
vrele(nd.ni_startdir);
ndp = &ind;
} else
error = 0;
}
/*
* If the public filehandle was used, check that this lookup
* didn't result in a filehandle outside the publicly exported
* filesystem.
*/
if (!error && ndp->ni_vp->v_mount != nfs_pub.np_mount) {
vput(nd.ni_vp);
error = EPERM;
}
}
if (dirp) {
if (v3)
dirattr_ret = VOP_GETATTR(dirp, &dirattr, cred,
procp);
vrele(dirp);
}
if (error) {
nfsm_reply(NFSX_POSTOPATTR(v3));
nfsm_srvpostop_attr(dirattr_ret, &dirattr);
return (0);
}
nqsrv_getl(nd.ni_startdir, ND_READ);
vrele(nd.ni_startdir);
nqsrv_getl(ndp->ni_startdir, ND_READ);
vrele(ndp->ni_startdir);
FREE(nd.ni_cnd.cn_pnbuf, M_NAMEI);
vp = nd.ni_vp;
vp = ndp->ni_vp;
bzero((caddr_t)fhp, sizeof(nfh));
fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
error = VFS_VPTOFH(vp, &fhp->fh_fid);
@ -491,7 +537,7 @@ nfsrv_readlink(nfsd, slp, procp, mrq)
uiop->uio_segflg = UIO_SYSSPACE;
uiop->uio_procp = (struct proc *)0;
if (error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
&rdonly, (nfsd->nd_flag & ND_KERBAUTH))) {
&rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE)) {
m_freem(mp3);
nfsm_reply(2 * NFSX_UNSIGNED);
nfsm_srvpostop_attr(1, (struct vattr *)0);
@ -574,7 +620,7 @@ nfsrv_read(nfsd, slp, procp, mrq)
}
nfsm_srvstrsiz(reqlen, NFS_SRVMAXDATA(nfsd));
if (error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
&rdonly, (nfsd->nd_flag & ND_KERBAUTH))) {
&rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE)) {
nfsm_reply(2 * NFSX_UNSIGNED);
nfsm_srvpostop_attr(1, (struct vattr *)0);
return (0);
@ -788,7 +834,7 @@ nfsrv_write(nfsd, slp, procp, mrq)
return (0);
}
if (error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
&rdonly, (nfsd->nd_flag & ND_KERBAUTH))) {
&rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE)) {
nfsm_reply(2 * NFSX_UNSIGNED);
nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
return (0);
@ -1066,7 +1112,7 @@ nfsrv_writegather(ndp, slp, procp, mrq)
v3 = (nfsd->nd_flag & ND_NFSV3);
forat_ret = aftat_ret = 1;
error = nfsrv_fhtovp(&nfsd->nd_fh, 1, &vp, cred, slp,
nfsd->nd_nam, &rdonly, (nfsd->nd_flag & ND_KERBAUTH));
nfsd->nd_nam, &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
if (!error) {
if (v3)
forat_ret = VOP_GETATTR(vp, &forat, cred, procp);
@ -1342,7 +1388,7 @@ nfsrv_create(nfsd, slp, procp, mrq)
nd.ni_cnd.cn_nameiop = CREATE;
nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART;
error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
&dirp, procp, (nfsd->nd_flag & ND_KERBAUTH));
&dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
if (dirp) {
if (v3)
dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
@ -1574,7 +1620,7 @@ nfsrv_mknod(nfsd, slp, procp, mrq)
nd.ni_cnd.cn_nameiop = CREATE;
nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART;
error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
&dirp, procp, (nfsd->nd_flag & ND_KERBAUTH));
&dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
if (dirp)
dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred, procp);
if (error) {
@ -1723,7 +1769,7 @@ nfsrv_remove(nfsd, slp, procp, mrq)
nd.ni_cnd.cn_nameiop = DELETE;
nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
&dirp, procp, (nfsd->nd_flag & ND_KERBAUTH));
&dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
if (dirp) {
if (v3)
dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
@ -1822,7 +1868,7 @@ nfsrv_rename(nfsd, slp, procp, mrq)
fromnd.ni_cnd.cn_nameiop = DELETE;
fromnd.ni_cnd.cn_flags = WANTPARENT | SAVESTART;
error = nfs_namei(&fromnd, ffhp, len, slp, nam, &md,
&dpos, &fdirp, procp, (nfsd->nd_flag & ND_KERBAUTH));
&dpos, &fdirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
if (fdirp) {
if (v3)
fdirfor_ret = VOP_GETATTR(fdirp, &fdirfor, cred,
@ -1848,7 +1894,7 @@ nfsrv_rename(nfsd, slp, procp, mrq)
tond.ni_cnd.cn_nameiop = RENAME;
tond.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART;
error = nfs_namei(&tond, tfhp, len2, slp, nam, &md,
&dpos, &tdirp, procp, (nfsd->nd_flag & ND_KERBAUTH));
&dpos, &tdirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
if (tdirp) {
if (v3)
tdirfor_ret = VOP_GETATTR(tdirp, &tdirfor, cred,
@ -2014,7 +2060,7 @@ nfsrv_link(nfsd, slp, procp, mrq)
nfsm_srvmtofh(dfhp);
nfsm_srvnamesiz(len);
if (error = nfsrv_fhtovp(fhp, FALSE, &vp, cred, slp, nam,
&rdonly, (nfsd->nd_flag & ND_KERBAUTH))) {
&rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE)) {
nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
nfsm_srvpostop_attr(getret, &at);
nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
@ -2028,7 +2074,7 @@ nfsrv_link(nfsd, slp, procp, mrq)
nd.ni_cnd.cn_nameiop = CREATE;
nd.ni_cnd.cn_flags = LOCKPARENT;
error = nfs_namei(&nd, dfhp, len, slp, nam, &md, &dpos,
&dirp, procp, (nfsd->nd_flag & ND_KERBAUTH));
&dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
if (dirp) {
if (v3)
dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
@ -2122,7 +2168,7 @@ nfsrv_symlink(nfsd, slp, procp, mrq)
nd.ni_cnd.cn_nameiop = CREATE;
nd.ni_cnd.cn_flags = LOCKPARENT | SAVESTART;
error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
&dirp, procp, (nfsd->nd_flag & ND_KERBAUTH));
&dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
if (dirp) {
if (v3)
dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
@ -2264,7 +2310,7 @@ nfsrv_mkdir(nfsd, slp, procp, mrq)
nd.ni_cnd.cn_nameiop = CREATE;
nd.ni_cnd.cn_flags = LOCKPARENT;
error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
&dirp, procp, (nfsd->nd_flag & ND_KERBAUTH));
&dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
if (dirp) {
if (v3)
dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
@ -2377,7 +2423,7 @@ nfsrv_rmdir(nfsd, slp, procp, mrq)
nd.ni_cnd.cn_nameiop = DELETE;
nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
&dirp, procp, (nfsd->nd_flag & ND_KERBAUTH));
&dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
if (dirp) {
if (v3)
dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
@ -2526,7 +2572,7 @@ nfsrv_readdir(nfsd, slp, procp, mrq)
siz = xfer;
fullsiz = siz;
if (error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
&rdonly, (nfsd->nd_flag & ND_KERBAUTH))) {
&rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE)) {
nfsm_reply(NFSX_UNSIGNED);
nfsm_srvpostop_attr(getret, &at);
return (0);
@ -2790,7 +2836,7 @@ nfsrv_readdirplus(nfsd, slp, procp, mrq)
siz = xfer;
fullsiz = siz;
if (error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
&rdonly, (nfsd->nd_flag & ND_KERBAUTH))) {
&rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE)) {
nfsm_reply(NFSX_UNSIGNED);
nfsm_srvpostop_attr(getret, &at);
return (0);
@ -3095,7 +3141,7 @@ nfsrv_commit(nfsd, slp, procp, mrq)
tl += 2;
cnt = fxdr_unsigned(int, *tl);
if (error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
&rdonly, (nfsd->nd_flag & ND_KERBAUTH))) {
&rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE)) {
nfsm_reply(2 * NFSX_UNSIGNED);
nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
return (0);
@ -3151,7 +3197,7 @@ nfsrv_statfs(nfsd, slp, procp, mrq)
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
if (error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
&rdonly, (nfsd->nd_flag & ND_KERBAUTH))) {
&rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE)) {
nfsm_reply(NFSX_UNSIGNED);
nfsm_srvpostop_attr(getret, &at);
return (0);
@ -3226,7 +3272,7 @@ nfsrv_fsinfo(nfsd, slp, procp, mrq)
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
if (error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
&rdonly, (nfsd->nd_flag & ND_KERBAUTH))) {
&rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE)) {
nfsm_reply(NFSX_UNSIGNED);
nfsm_srvpostop_attr(getret, &at);
return (0);
@ -3297,7 +3343,7 @@ nfsrv_pathconf(nfsd, slp, procp, mrq)
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
if (error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
&rdonly, (nfsd->nd_flag & ND_KERBAUTH))) {
&rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE)) {
nfsm_reply(NFSX_UNSIGNED);
nfsm_srvpostop_attr(getret, &at);
return (0);

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_subs.c 8.3 (Berkeley) 1/4/94
* $Id: nfs_subs.c,v 1.37 1997/02/22 09:42:41 peter Exp $
* $Id: nfs_subs.c,v 1.38 1997/04/04 17:49:29 dfr Exp $
*/
/*
@ -53,6 +53,7 @@
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/malloc.h>
#include <sys/dirent.h>
#ifdef VFS_LKM
#include <sys/sysent.h>
#include <sys/syscall.h>
@ -560,6 +561,8 @@ extern int nfssvc(struct proc *, struct nfssvc_args *, int *);
LIST_HEAD(nfsnodehashhead, nfsnode);
int nfs_webnamei __P((struct nameidata *, struct vnode *, struct proc *));
/*
* Create the header for an rpc request packet
* The hsiz is the size of the rest of the nfs request header.
@ -1412,10 +1415,16 @@ nfs_getattrcache(vp, vaper)
#ifndef NFS_NOSERVER
/*
* Set up nameidata for a lookup() call and do it
* Set up nameidata for a lookup() call and do it.
*
* If pubflag is set, this call is done for a lookup operation on the
* public filehandle. In that case we allow crossing mountpoints and
* absolute pathnames. However, the caller is expected to check that
* the lookup result is within the public fs, and deny access if
* it is not.
*/
int
nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, retdirp, p, kerbflag)
nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, retdirp, p, kerbflag, pubflag)
register struct nameidata *ndp;
fhandle_t *fhp;
int len;
@ -1425,13 +1434,15 @@ nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, retdirp, p, kerbflag)
caddr_t *dposp;
struct vnode **retdirp;
struct proc *p;
int kerbflag;
int kerbflag, pubflag;
{
register int i, rem;
register struct mbuf *md;
register char *fromcp, *tocp;
register char *fromcp, *tocp, *cp;
struct iovec aiov;
struct uio auio;
struct vnode *dp;
int error, rdonly;
int error, rdonly, linklen;
struct componentname *cnp = &ndp->ni_cnd;
*retdirp = (struct vnode *)0;
@ -1455,7 +1466,7 @@ nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, retdirp, p, kerbflag)
fromcp = mtod(md, caddr_t);
rem = md->m_len;
}
if (*fromcp == '\0' || *fromcp == '/') {
if (*fromcp == '\0' || (!pubflag && *fromcp == '/')) {
error = EACCES;
goto out;
}
@ -1473,55 +1484,170 @@ nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, retdirp, p, kerbflag)
else if (error = nfs_adv(mdp, dposp, len, rem))
goto out;
}
ndp->ni_pathlen = tocp - cnp->cn_pnbuf;
cnp->cn_nameptr = cnp->cn_pnbuf;
/*
* Extract and set starting directory.
*/
if (error = nfsrv_fhtovp(fhp, FALSE, &dp, ndp->ni_cnd.cn_cred, slp,
nam, &rdonly, kerbflag))
error = nfsrv_fhtovp(fhp, FALSE, &dp, ndp->ni_cnd.cn_cred, slp,
nam, &rdonly, kerbflag, pubflag);
if (error)
goto out;
if (dp->v_type != VDIR) {
vrele(dp);
error = ENOTDIR;
goto out;
}
VREF(dp);
*retdirp = dp;
ndp->ni_startdir = dp;
if (rdonly)
cnp->cn_flags |= (NOCROSSMOUNT | RDONLY);
else
cnp->cn_flags |= NOCROSSMOUNT;
cnp->cn_flags |= RDONLY;
if (pubflag) {
/*
* Oh joy. For WebNFS, handle those pesky '%' escapes,
* and the 'native path' indicator.
*/
MALLOC(cp, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
fromcp = cnp->cn_pnbuf;
tocp = cp;
if ((unsigned char)*fromcp >= WEBNFS_SPECCHAR_START) {
switch ((unsigned char)*fromcp) {
case WEBNFS_NATIVE_CHAR:
/*
* 'Native' path for us is the same
* as a path according to the NFS spec,
* just skip the escape char.
*/
fromcp++;
break;
/*
* More may be added in the future, range 0x80-0xff
*/
default:
error = EIO;
FREE(cp, M_NAMEI);
goto out;
}
}
/*
* Translate the '%' escapes, URL-style.
*/
while (*fromcp != '\0') {
if (*fromcp == WEBNFS_ESC_CHAR) {
if (fromcp[1] != '\0' && fromcp[2] != '\0') {
fromcp++;
*tocp++ = HEXSTRTOI(fromcp);
fromcp += 2;
continue;
} else {
error = ENOENT;
FREE(cp, M_NAMEI);
goto out;
}
} else
*tocp++ = *fromcp++;
}
*tocp = '\0';
FREE(cnp->cn_pnbuf, M_NAMEI);
cnp->cn_pnbuf = cp;
}
ndp->ni_pathlen = (tocp - cnp->cn_pnbuf) + 1;
ndp->ni_segflg = UIO_SYSSPACE;
if (pubflag) {
ndp->ni_rootdir = rootvnode;
ndp->ni_loopcnt = 0;
if (cnp->cn_pnbuf[0] == '/')
dp = rootvnode;
} else {
cnp->cn_flags |= NOCROSSMOUNT;
}
cnp->cn_proc = p;
VREF(dp);
for (;;) {
cnp->cn_nameptr = cnp->cn_pnbuf;
ndp->ni_startdir = dp;
/*
* And call lookup() to do the real work
*/
cnp->cn_proc = p;
if (error = lookup(ndp))
goto out;
break;
/*
* Check for encountering a symbolic link
*/
if (cnp->cn_flags & ISSYMLINK) {
if ((cnp->cn_flags & ISSYMLINK) == 0) {
nfsrv_object_create(ndp->ni_vp);
if (cnp->cn_flags & (SAVENAME | SAVESTART)) {
cnp->cn_flags |= HASBUF;
return (0);
}
break;
} else {
if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1)
vput(ndp->ni_dvp);
else
VOP_UNLOCK(ndp->ni_dvp, 0, p);
if (!pubflag) {
vrele(ndp->ni_dvp);
vput(ndp->ni_vp);
ndp->ni_vp = NULL;
error = EINVAL;
break;
}
if (ndp->ni_loopcnt++ >= MAXSYMLINKS) {
error = ELOOP;
break;
}
if (ndp->ni_pathlen > 0)
MALLOC(cp, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
else
cp = cnp->cn_pnbuf;
aiov.iov_base = cp;
aiov.iov_len = MAXPATHLEN;
auio.uio_iov = &aiov;
auio.uio_iovcnt = 1;
auio.uio_offset = 0;
auio.uio_rw = UIO_READ;
auio.uio_segflg = UIO_SYSSPACE;
auio.uio_procp = (struct proc *)0;
auio.uio_resid = MAXPATHLEN;
error = VOP_READLINK(ndp->ni_vp, &auio, cnp->cn_cred);
if (error) {
badlink:
if (ndp->ni_pathlen > 1)
FREE(cp, M_NAMEI);
break;
}
linklen = MAXPATHLEN - auio.uio_resid;
if (linklen == 0) {
error = ENOENT;
goto badlink;
}
if (linklen + ndp->ni_pathlen >= MAXPATHLEN) {
error = ENAMETOOLONG;
goto badlink;
}
if (ndp->ni_pathlen > 1) {
bcopy(ndp->ni_next, cp + linklen, ndp->ni_pathlen);
FREE(cnp->cn_pnbuf, M_NAMEI);
cnp->cn_pnbuf = cp;
} else
cnp->cn_pnbuf[linklen] = '\0';
ndp->ni_pathlen += linklen;
vput(ndp->ni_vp);
ndp->ni_vp = NULL;
error = EINVAL;
goto out;
}
nfsrv_object_create(ndp->ni_vp);
/*
* Check for saved name request
*/
if (cnp->cn_flags & (SAVENAME | SAVESTART)) {
cnp->cn_flags |= HASBUF;
return (0);
dp = ndp->ni_dvp;
/*
* Check if root directory should replace current directory.
*/
if (cnp->cn_pnbuf[0] == '/') {
vrele(dp);
dp = ndp->ni_rootdir;
VREF(dp);
}
}
}
out:
FREE(cnp->cn_pnbuf, M_NAMEI);
return (error);
@ -1700,7 +1826,7 @@ nfsm_srvfattr(nfsd, vap, fp)
* - if not lockflag unlock it with VOP_UNLOCK()
*/
int
nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag)
nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag, pubflag)
fhandle_t *fhp;
int lockflag;
struct vnode **vpp;
@ -1709,6 +1835,7 @@ nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag)
struct mbuf *nam;
int *rdonlyp;
int kerbflag;
int pubflag;
{
struct proc *p = curproc; /* XXX */
register struct mount *mp;
@ -1717,6 +1844,13 @@ nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag)
int error, exflags;
*vpp = (struct vnode *)0;
if (nfs_ispublicfh(fhp)) {
if (!pubflag || !nfs_pub.np_valid)
return (ESTALE);
fhp = &nfs_pub.np_handle;
}
mp = vfs_getvfs(&fhp->fh_fsid);
if (!mp)
return (ESTALE);
@ -1752,6 +1886,25 @@ nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag)
return (0);
}
/*
* WebNFS: check if a filehandle is a public filehandle. For v3, this
* means a length of 0, for v2 it means all zeroes. nfsm_srvmtofh has
* transformed this to all zeroes in both cases, so check for it.
*/
int
nfs_ispublicfh(fhp)
fhandle_t *fhp;
{
char *cp = (char *)fhp;
int i;
for (i = 0; i < NFSX_V3FH; i++)
if (*cp++ != 0)
return (FALSE);
return (TRUE);
}
#endif /* NFS_NOSERVER */
/*
* This function compares two net addresses by family and returns TRUE

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_syscalls.c 8.5 (Berkeley) 3/30/95
* $Id: nfs_syscalls.c,v 1.24 1997/05/13 17:25:44 dfr Exp $
* $Id: nfs_syscalls.c,v 1.25 1997/06/25 21:07:26 tegge Exp $
*/
#include <sys/param.h>
@ -1129,7 +1129,8 @@ nfsrv_init(terminating)
free((caddr_t)slp, M_NFSSVC);
}
nfsrv_cleancache(); /* And clear out server cache */
}
} else
nfs_pub.np_valid = 0;
TAILQ_INIT(&nfssvc_sockhead);
nfssvc_sockhead_flag &= ~SLP_INIT;

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfsm_subs.h 8.2 (Berkeley) 3/30/95
* $Id$
* $Id: nfsm_subs.h,v 1.12 1997/02/22 09:42:48 peter Exp $
*/
@ -363,18 +363,24 @@ struct mbuf *nfsm_rpchead __P((struct ucred *cr, int nmflag, int procid,
} }
#define nfsm_srvmtofh(f) \
{ if (nfsd->nd_flag & ND_NFSV3) { \
{ int fhlen = NFSX_V3FH; \
if (nfsd->nd_flag & ND_NFSV3) { \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
if (fxdr_unsigned(int, *tl) != NFSX_V3FH) { \
fhlen = fxdr_unsigned(int, *tl); \
if (fhlen == 0) { \
bzero((caddr_t)(f), NFSX_V3FH); \
} else if (fhlen != NFSX_V3FH) { \
error = EBADRPC; \
nfsm_reply(0); \
} \
} \
nfsm_dissect(tl, u_long *, NFSX_V3FH); \
bcopy((caddr_t)tl, (caddr_t)(f), NFSX_V3FH); \
if ((nfsd->nd_flag & ND_NFSV3) == 0) \
nfsm_adv(NFSX_V2FH - NFSX_V3FH); \
}
if (fhlen != 0) { \
nfsm_dissect(tl, u_long *, NFSX_V3FH); \
bcopy((caddr_t)tl, (caddr_t)(f), NFSX_V3FH); \
if ((nfsd->nd_flag & ND_NFSV3) == 0) \
nfsm_adv(NFSX_V2FH - NFSX_V3FH); \
} \
}
#define nfsm_clget \
if (bp >= be) { \

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs.h 8.4 (Berkeley) 5/1/95
* $Id: nfs.h,v 1.27 1997/05/19 14:36:46 dfr Exp $
* $Id: nfs.h,v 1.28 1997/06/03 17:22:45 dfr Exp $
*/
#ifndef _NFS_NFS_H_
@ -522,6 +522,30 @@ extern int nfsd_head_flag;
!bcmp((caddr_t)&(o)->nd_cr, (caddr_t)&(n)->nd_cr, \
sizeof (struct ucred)))
/*
* Defines for WebNFS
*/
#define WEBNFS_ESC_CHAR '%'
#define WEBNFS_SPECCHAR_START 0x80
#define WEBNFS_NATIVE_CHAR 0x80
/*
* ..
* Possibly more here in the future.
*/
/*
* Macro for converting escape characters in WebNFS pathnames.
* Should really be in libkern.
*/
#define HEXTOC(c) \
((c) >= 'a' ? ((c) - ('a' - 10)) : \
((c) >= 'A' ? ((c) - ('A' - 10)) : ((c) - '0')))
#define HEXSTRTOI(p) \
((HEXTOC(p[0]) << 4) + HEXTOC(p[1]))
#ifdef NFS_DEBUG
extern int nfs_debug;
@ -564,7 +588,7 @@ void nfsm_srvpostopattr __P((struct nfsrv_descript *,int,struct vattr *,struct m
int netaddr_match __P((int,union nethostaddr *,struct mbuf *));
int nfs_request __P((struct vnode *,struct mbuf *,int,struct proc *,struct ucred *,struct mbuf **,struct mbuf **,caddr_t *));
int nfs_loadattrcache __P((struct vnode **,struct mbuf **,caddr_t *,struct vattr *));
int nfs_namei __P((struct nameidata *,fhandle_t *,int,struct nfssvc_sock *,struct mbuf *,struct mbuf **,caddr_t *,struct vnode **,struct proc *,int));
int nfs_namei __P((struct nameidata *,fhandle_t *,int,struct nfssvc_sock *,struct mbuf *,struct mbuf **,caddr_t *,struct vnode **,struct proc *,int,int));
void nfsm_adj __P((struct mbuf *,int,int));
int nfsm_mbuftouio __P((struct mbuf **,struct uio *,int,caddr_t *));
void nfsrv_initcache __P((void));
@ -606,7 +630,10 @@ int nfsrv_create __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
struct proc *procp, struct mbuf **mrq));
int nfsrv_fhtovp __P((fhandle_t *,int,struct vnode **,
struct ucred *,struct nfssvc_sock *,struct mbuf *,
int *,int));
int *,int,int));
int nfsrv_setpublicfs __P((struct mount *, struct netexport *,
struct export_args *));
int nfs_ispublicfh __P((fhandle_t *));
int nfsrv_fsinfo __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
struct proc *procp, struct mbuf **mrq));
int nfsrv_getattr __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_syscalls.c 8.5 (Berkeley) 3/30/95
* $Id: nfs_syscalls.c,v 1.24 1997/05/13 17:25:44 dfr Exp $
* $Id: nfs_syscalls.c,v 1.25 1997/06/25 21:07:26 tegge Exp $
*/
#include <sys/param.h>
@ -1129,7 +1129,8 @@ nfsrv_init(terminating)
free((caddr_t)slp, M_NFSSVC);
}
nfsrv_cleancache(); /* And clear out server cache */
}
} else
nfs_pub.np_valid = 0;
TAILQ_INIT(&nfssvc_sockhead);
nfssvc_sockhead_flag &= ~SLP_INIT;

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_subs.c 8.3 (Berkeley) 1/4/94
* $Id: nfs_subs.c,v 1.37 1997/02/22 09:42:41 peter Exp $
* $Id: nfs_subs.c,v 1.38 1997/04/04 17:49:29 dfr Exp $
*/
/*
@ -53,6 +53,7 @@
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/malloc.h>
#include <sys/dirent.h>
#ifdef VFS_LKM
#include <sys/sysent.h>
#include <sys/syscall.h>
@ -560,6 +561,8 @@ extern int nfssvc(struct proc *, struct nfssvc_args *, int *);
LIST_HEAD(nfsnodehashhead, nfsnode);
int nfs_webnamei __P((struct nameidata *, struct vnode *, struct proc *));
/*
* Create the header for an rpc request packet
* The hsiz is the size of the rest of the nfs request header.
@ -1412,10 +1415,16 @@ nfs_getattrcache(vp, vaper)
#ifndef NFS_NOSERVER
/*
* Set up nameidata for a lookup() call and do it
* Set up nameidata for a lookup() call and do it.
*
* If pubflag is set, this call is done for a lookup operation on the
* public filehandle. In that case we allow crossing mountpoints and
* absolute pathnames. However, the caller is expected to check that
* the lookup result is within the public fs, and deny access if
* it is not.
*/
int
nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, retdirp, p, kerbflag)
nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, retdirp, p, kerbflag, pubflag)
register struct nameidata *ndp;
fhandle_t *fhp;
int len;
@ -1425,13 +1434,15 @@ nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, retdirp, p, kerbflag)
caddr_t *dposp;
struct vnode **retdirp;
struct proc *p;
int kerbflag;
int kerbflag, pubflag;
{
register int i, rem;
register struct mbuf *md;
register char *fromcp, *tocp;
register char *fromcp, *tocp, *cp;
struct iovec aiov;
struct uio auio;
struct vnode *dp;
int error, rdonly;
int error, rdonly, linklen;
struct componentname *cnp = &ndp->ni_cnd;
*retdirp = (struct vnode *)0;
@ -1455,7 +1466,7 @@ nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, retdirp, p, kerbflag)
fromcp = mtod(md, caddr_t);
rem = md->m_len;
}
if (*fromcp == '\0' || *fromcp == '/') {
if (*fromcp == '\0' || (!pubflag && *fromcp == '/')) {
error = EACCES;
goto out;
}
@ -1473,55 +1484,170 @@ nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, retdirp, p, kerbflag)
else if (error = nfs_adv(mdp, dposp, len, rem))
goto out;
}
ndp->ni_pathlen = tocp - cnp->cn_pnbuf;
cnp->cn_nameptr = cnp->cn_pnbuf;
/*
* Extract and set starting directory.
*/
if (error = nfsrv_fhtovp(fhp, FALSE, &dp, ndp->ni_cnd.cn_cred, slp,
nam, &rdonly, kerbflag))
error = nfsrv_fhtovp(fhp, FALSE, &dp, ndp->ni_cnd.cn_cred, slp,
nam, &rdonly, kerbflag, pubflag);
if (error)
goto out;
if (dp->v_type != VDIR) {
vrele(dp);
error = ENOTDIR;
goto out;
}
VREF(dp);
*retdirp = dp;
ndp->ni_startdir = dp;
if (rdonly)
cnp->cn_flags |= (NOCROSSMOUNT | RDONLY);
else
cnp->cn_flags |= NOCROSSMOUNT;
cnp->cn_flags |= RDONLY;
if (pubflag) {
/*
* Oh joy. For WebNFS, handle those pesky '%' escapes,
* and the 'native path' indicator.
*/
MALLOC(cp, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
fromcp = cnp->cn_pnbuf;
tocp = cp;
if ((unsigned char)*fromcp >= WEBNFS_SPECCHAR_START) {
switch ((unsigned char)*fromcp) {
case WEBNFS_NATIVE_CHAR:
/*
* 'Native' path for us is the same
* as a path according to the NFS spec,
* just skip the escape char.
*/
fromcp++;
break;
/*
* More may be added in the future, range 0x80-0xff
*/
default:
error = EIO;
FREE(cp, M_NAMEI);
goto out;
}
}
/*
* Translate the '%' escapes, URL-style.
*/
while (*fromcp != '\0') {
if (*fromcp == WEBNFS_ESC_CHAR) {
if (fromcp[1] != '\0' && fromcp[2] != '\0') {
fromcp++;
*tocp++ = HEXSTRTOI(fromcp);
fromcp += 2;
continue;
} else {
error = ENOENT;
FREE(cp, M_NAMEI);
goto out;
}
} else
*tocp++ = *fromcp++;
}
*tocp = '\0';
FREE(cnp->cn_pnbuf, M_NAMEI);
cnp->cn_pnbuf = cp;
}
ndp->ni_pathlen = (tocp - cnp->cn_pnbuf) + 1;
ndp->ni_segflg = UIO_SYSSPACE;
if (pubflag) {
ndp->ni_rootdir = rootvnode;
ndp->ni_loopcnt = 0;
if (cnp->cn_pnbuf[0] == '/')
dp = rootvnode;
} else {
cnp->cn_flags |= NOCROSSMOUNT;
}
cnp->cn_proc = p;
VREF(dp);
for (;;) {
cnp->cn_nameptr = cnp->cn_pnbuf;
ndp->ni_startdir = dp;
/*
* And call lookup() to do the real work
*/
cnp->cn_proc = p;
if (error = lookup(ndp))
goto out;
break;
/*
* Check for encountering a symbolic link
*/
if (cnp->cn_flags & ISSYMLINK) {
if ((cnp->cn_flags & ISSYMLINK) == 0) {
nfsrv_object_create(ndp->ni_vp);
if (cnp->cn_flags & (SAVENAME | SAVESTART)) {
cnp->cn_flags |= HASBUF;
return (0);
}
break;
} else {
if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1)
vput(ndp->ni_dvp);
else
VOP_UNLOCK(ndp->ni_dvp, 0, p);
if (!pubflag) {
vrele(ndp->ni_dvp);
vput(ndp->ni_vp);
ndp->ni_vp = NULL;
error = EINVAL;
break;
}
if (ndp->ni_loopcnt++ >= MAXSYMLINKS) {
error = ELOOP;
break;
}
if (ndp->ni_pathlen > 0)
MALLOC(cp, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
else
cp = cnp->cn_pnbuf;
aiov.iov_base = cp;
aiov.iov_len = MAXPATHLEN;
auio.uio_iov = &aiov;
auio.uio_iovcnt = 1;
auio.uio_offset = 0;
auio.uio_rw = UIO_READ;
auio.uio_segflg = UIO_SYSSPACE;
auio.uio_procp = (struct proc *)0;
auio.uio_resid = MAXPATHLEN;
error = VOP_READLINK(ndp->ni_vp, &auio, cnp->cn_cred);
if (error) {
badlink:
if (ndp->ni_pathlen > 1)
FREE(cp, M_NAMEI);
break;
}
linklen = MAXPATHLEN - auio.uio_resid;
if (linklen == 0) {
error = ENOENT;
goto badlink;
}
if (linklen + ndp->ni_pathlen >= MAXPATHLEN) {
error = ENAMETOOLONG;
goto badlink;
}
if (ndp->ni_pathlen > 1) {
bcopy(ndp->ni_next, cp + linklen, ndp->ni_pathlen);
FREE(cnp->cn_pnbuf, M_NAMEI);
cnp->cn_pnbuf = cp;
} else
cnp->cn_pnbuf[linklen] = '\0';
ndp->ni_pathlen += linklen;
vput(ndp->ni_vp);
ndp->ni_vp = NULL;
error = EINVAL;
goto out;
}
nfsrv_object_create(ndp->ni_vp);
/*
* Check for saved name request
*/
if (cnp->cn_flags & (SAVENAME | SAVESTART)) {
cnp->cn_flags |= HASBUF;
return (0);
dp = ndp->ni_dvp;
/*
* Check if root directory should replace current directory.
*/
if (cnp->cn_pnbuf[0] == '/') {
vrele(dp);
dp = ndp->ni_rootdir;
VREF(dp);
}
}
}
out:
FREE(cnp->cn_pnbuf, M_NAMEI);
return (error);
@ -1700,7 +1826,7 @@ nfsm_srvfattr(nfsd, vap, fp)
* - if not lockflag unlock it with VOP_UNLOCK()
*/
int
nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag)
nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag, pubflag)
fhandle_t *fhp;
int lockflag;
struct vnode **vpp;
@ -1709,6 +1835,7 @@ nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag)
struct mbuf *nam;
int *rdonlyp;
int kerbflag;
int pubflag;
{
struct proc *p = curproc; /* XXX */
register struct mount *mp;
@ -1717,6 +1844,13 @@ nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag)
int error, exflags;
*vpp = (struct vnode *)0;
if (nfs_ispublicfh(fhp)) {
if (!pubflag || !nfs_pub.np_valid)
return (ESTALE);
fhp = &nfs_pub.np_handle;
}
mp = vfs_getvfs(&fhp->fh_fsid);
if (!mp)
return (ESTALE);
@ -1752,6 +1886,25 @@ nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag)
return (0);
}
/*
* WebNFS: check if a filehandle is a public filehandle. For v3, this
* means a length of 0, for v2 it means all zeroes. nfsm_srvmtofh has
* transformed this to all zeroes in both cases, so check for it.
*/
int
nfs_ispublicfh(fhp)
fhandle_t *fhp;
{
char *cp = (char *)fhp;
int i;
for (i = 0; i < NFSX_V3FH; i++)
if (*cp++ != 0)
return (FALSE);
return (TRUE);
}
#endif /* NFS_NOSERVER */
/*
* This function compares two net addresses by family and returns TRUE

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs.h 8.4 (Berkeley) 5/1/95
* $Id: nfs.h,v 1.27 1997/05/19 14:36:46 dfr Exp $
* $Id: nfs.h,v 1.28 1997/06/03 17:22:45 dfr Exp $
*/
#ifndef _NFS_NFS_H_
@ -522,6 +522,30 @@ extern int nfsd_head_flag;
!bcmp((caddr_t)&(o)->nd_cr, (caddr_t)&(n)->nd_cr, \
sizeof (struct ucred)))
/*
* Defines for WebNFS
*/
#define WEBNFS_ESC_CHAR '%'
#define WEBNFS_SPECCHAR_START 0x80
#define WEBNFS_NATIVE_CHAR 0x80
/*
* ..
* Possibly more here in the future.
*/
/*
* Macro for converting escape characters in WebNFS pathnames.
* Should really be in libkern.
*/
#define HEXTOC(c) \
((c) >= 'a' ? ((c) - ('a' - 10)) : \
((c) >= 'A' ? ((c) - ('A' - 10)) : ((c) - '0')))
#define HEXSTRTOI(p) \
((HEXTOC(p[0]) << 4) + HEXTOC(p[1]))
#ifdef NFS_DEBUG
extern int nfs_debug;
@ -564,7 +588,7 @@ void nfsm_srvpostopattr __P((struct nfsrv_descript *,int,struct vattr *,struct m
int netaddr_match __P((int,union nethostaddr *,struct mbuf *));
int nfs_request __P((struct vnode *,struct mbuf *,int,struct proc *,struct ucred *,struct mbuf **,struct mbuf **,caddr_t *));
int nfs_loadattrcache __P((struct vnode **,struct mbuf **,caddr_t *,struct vattr *));
int nfs_namei __P((struct nameidata *,fhandle_t *,int,struct nfssvc_sock *,struct mbuf *,struct mbuf **,caddr_t *,struct vnode **,struct proc *,int));
int nfs_namei __P((struct nameidata *,fhandle_t *,int,struct nfssvc_sock *,struct mbuf *,struct mbuf **,caddr_t *,struct vnode **,struct proc *,int,int));
void nfsm_adj __P((struct mbuf *,int,int));
int nfsm_mbuftouio __P((struct mbuf **,struct uio *,int,caddr_t *));
void nfsrv_initcache __P((void));
@ -606,7 +630,10 @@ int nfsrv_create __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
struct proc *procp, struct mbuf **mrq));
int nfsrv_fhtovp __P((fhandle_t *,int,struct vnode **,
struct ucred *,struct nfssvc_sock *,struct mbuf *,
int *,int));
int *,int,int));
int nfsrv_setpublicfs __P((struct mount *, struct netexport *,
struct export_args *));
int nfs_ispublicfh __P((fhandle_t *));
int nfsrv_fsinfo __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
struct proc *procp, struct mbuf **mrq));
int nfsrv_getattr __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfsm_subs.h 8.2 (Berkeley) 3/30/95
* $Id$
* $Id: nfsm_subs.h,v 1.12 1997/02/22 09:42:48 peter Exp $
*/
@ -363,18 +363,24 @@ struct mbuf *nfsm_rpchead __P((struct ucred *cr, int nmflag, int procid,
} }
#define nfsm_srvmtofh(f) \
{ if (nfsd->nd_flag & ND_NFSV3) { \
{ int fhlen = NFSX_V3FH; \
if (nfsd->nd_flag & ND_NFSV3) { \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
if (fxdr_unsigned(int, *tl) != NFSX_V3FH) { \
fhlen = fxdr_unsigned(int, *tl); \
if (fhlen == 0) { \
bzero((caddr_t)(f), NFSX_V3FH); \
} else if (fhlen != NFSX_V3FH) { \
error = EBADRPC; \
nfsm_reply(0); \
} \
} \
nfsm_dissect(tl, u_long *, NFSX_V3FH); \
bcopy((caddr_t)tl, (caddr_t)(f), NFSX_V3FH); \
if ((nfsd->nd_flag & ND_NFSV3) == 0) \
nfsm_adv(NFSX_V2FH - NFSX_V3FH); \
}
if (fhlen != 0) { \
nfsm_dissect(tl, u_long *, NFSX_V3FH); \
bcopy((caddr_t)tl, (caddr_t)(f), NFSX_V3FH); \
if ((nfsd->nd_flag & ND_NFSV3) == 0) \
nfsm_adv(NFSX_V2FH - NFSX_V3FH); \
} \
}
#define nfsm_clget \
if (bp >= be) { \

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs.h 8.4 (Berkeley) 5/1/95
* $Id: nfs.h,v 1.27 1997/05/19 14:36:46 dfr Exp $
* $Id: nfs.h,v 1.28 1997/06/03 17:22:45 dfr Exp $
*/
#ifndef _NFS_NFS_H_
@ -522,6 +522,30 @@ extern int nfsd_head_flag;
!bcmp((caddr_t)&(o)->nd_cr, (caddr_t)&(n)->nd_cr, \
sizeof (struct ucred)))
/*
* Defines for WebNFS
*/
#define WEBNFS_ESC_CHAR '%'
#define WEBNFS_SPECCHAR_START 0x80
#define WEBNFS_NATIVE_CHAR 0x80
/*
* ..
* Possibly more here in the future.
*/
/*
* Macro for converting escape characters in WebNFS pathnames.
* Should really be in libkern.
*/
#define HEXTOC(c) \
((c) >= 'a' ? ((c) - ('a' - 10)) : \
((c) >= 'A' ? ((c) - ('A' - 10)) : ((c) - '0')))
#define HEXSTRTOI(p) \
((HEXTOC(p[0]) << 4) + HEXTOC(p[1]))
#ifdef NFS_DEBUG
extern int nfs_debug;
@ -564,7 +588,7 @@ void nfsm_srvpostopattr __P((struct nfsrv_descript *,int,struct vattr *,struct m
int netaddr_match __P((int,union nethostaddr *,struct mbuf *));
int nfs_request __P((struct vnode *,struct mbuf *,int,struct proc *,struct ucred *,struct mbuf **,struct mbuf **,caddr_t *));
int nfs_loadattrcache __P((struct vnode **,struct mbuf **,caddr_t *,struct vattr *));
int nfs_namei __P((struct nameidata *,fhandle_t *,int,struct nfssvc_sock *,struct mbuf *,struct mbuf **,caddr_t *,struct vnode **,struct proc *,int));
int nfs_namei __P((struct nameidata *,fhandle_t *,int,struct nfssvc_sock *,struct mbuf *,struct mbuf **,caddr_t *,struct vnode **,struct proc *,int,int));
void nfsm_adj __P((struct mbuf *,int,int));
int nfsm_mbuftouio __P((struct mbuf **,struct uio *,int,caddr_t *));
void nfsrv_initcache __P((void));
@ -606,7 +630,10 @@ int nfsrv_create __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
struct proc *procp, struct mbuf **mrq));
int nfsrv_fhtovp __P((fhandle_t *,int,struct vnode **,
struct ucred *,struct nfssvc_sock *,struct mbuf *,
int *,int));
int *,int,int));
int nfsrv_setpublicfs __P((struct mount *, struct netexport *,
struct export_args *));
int nfs_ispublicfh __P((fhandle_t *));
int nfsrv_fsinfo __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
struct proc *procp, struct mbuf **mrq));
int nfsrv_getattr __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs.h 8.4 (Berkeley) 5/1/95
* $Id: nfs.h,v 1.27 1997/05/19 14:36:46 dfr Exp $
* $Id: nfs.h,v 1.28 1997/06/03 17:22:45 dfr Exp $
*/
#ifndef _NFS_NFS_H_
@ -522,6 +522,30 @@ extern int nfsd_head_flag;
!bcmp((caddr_t)&(o)->nd_cr, (caddr_t)&(n)->nd_cr, \
sizeof (struct ucred)))
/*
* Defines for WebNFS
*/
#define WEBNFS_ESC_CHAR '%'
#define WEBNFS_SPECCHAR_START 0x80
#define WEBNFS_NATIVE_CHAR 0x80
/*
* ..
* Possibly more here in the future.
*/
/*
* Macro for converting escape characters in WebNFS pathnames.
* Should really be in libkern.
*/
#define HEXTOC(c) \
((c) >= 'a' ? ((c) - ('a' - 10)) : \
((c) >= 'A' ? ((c) - ('A' - 10)) : ((c) - '0')))
#define HEXSTRTOI(p) \
((HEXTOC(p[0]) << 4) + HEXTOC(p[1]))
#ifdef NFS_DEBUG
extern int nfs_debug;
@ -564,7 +588,7 @@ void nfsm_srvpostopattr __P((struct nfsrv_descript *,int,struct vattr *,struct m
int netaddr_match __P((int,union nethostaddr *,struct mbuf *));
int nfs_request __P((struct vnode *,struct mbuf *,int,struct proc *,struct ucred *,struct mbuf **,struct mbuf **,caddr_t *));
int nfs_loadattrcache __P((struct vnode **,struct mbuf **,caddr_t *,struct vattr *));
int nfs_namei __P((struct nameidata *,fhandle_t *,int,struct nfssvc_sock *,struct mbuf *,struct mbuf **,caddr_t *,struct vnode **,struct proc *,int));
int nfs_namei __P((struct nameidata *,fhandle_t *,int,struct nfssvc_sock *,struct mbuf *,struct mbuf **,caddr_t *,struct vnode **,struct proc *,int,int));
void nfsm_adj __P((struct mbuf *,int,int));
int nfsm_mbuftouio __P((struct mbuf **,struct uio *,int,caddr_t *));
void nfsrv_initcache __P((void));
@ -606,7 +630,10 @@ int nfsrv_create __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
struct proc *procp, struct mbuf **mrq));
int nfsrv_fhtovp __P((fhandle_t *,int,struct vnode **,
struct ucred *,struct nfssvc_sock *,struct mbuf *,
int *,int));
int *,int,int));
int nfsrv_setpublicfs __P((struct mount *, struct netexport *,
struct export_args *));
int nfs_ispublicfh __P((fhandle_t *));
int nfsrv_fsinfo __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
struct proc *procp, struct mbuf **mrq));
int nfsrv_getattr __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_serv.c 8.3 (Berkeley) 1/12/94
* $Id: nfs_serv.c,v 1.43 1997/06/03 13:56:54 dfr Exp $
* $Id: nfs_serv.c,v 1.44 1997/06/14 11:19:35 bde Exp $
*/
/*
@ -140,7 +140,7 @@ nfsrv3_access(nfsd, slp, procp, mrq)
nfsm_srvmtofh(fhp);
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
if (error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
&rdonly, (nfsd->nd_flag & ND_KERBAUTH))) {
&rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE)) {
nfsm_reply(NFSX_UNSIGNED);
nfsm_srvpostop_attr(1, (struct vattr *)0);
return (0);
@ -204,7 +204,7 @@ nfsrv_getattr(nfsd, slp, procp, mrq)
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
if (error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
&rdonly, (nfsd->nd_flag & ND_KERBAUTH))) {
&rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE)) {
nfsm_reply(0);
return (0);
}
@ -296,7 +296,7 @@ nfsrv_setattr(nfsd, slp, procp, mrq)
* Now that we have all the fields, lets do it.
*/
if (error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
&rdonly, (nfsd->nd_flag & ND_KERBAUTH))) {
&rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE)) {
nfsm_reply(2 * NFSX_UNSIGNED);
nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap);
return (0);
@ -365,7 +365,7 @@ nfsrv_lookup(nfsd, slp, procp, mrq)
caddr_t dpos = nfsd->nd_dpos;
struct ucred *cred = &nfsd->nd_cr;
register struct nfs_fattr *fp;
struct nameidata nd;
struct nameidata nd, ind, *ndp = &nd;
struct vnode *vp, *dirp;
nfsfh_t nfh;
fhandle_t *fhp;
@ -374,7 +374,7 @@ nfsrv_lookup(nfsd, slp, procp, mrq)
register long t1;
caddr_t bpos;
int error = 0, cache, len, dirattr_ret = 1;
int v3 = (nfsd->nd_flag & ND_NFSV3);
int v3 = (nfsd->nd_flag & ND_NFSV3), pubflag;
char *cp2;
struct mbuf *mb, *mb2, *mreq;
struct vattr va, dirattr, *vap = &va;
@ -383,26 +383,72 @@ nfsrv_lookup(nfsd, slp, procp, mrq)
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
nfsm_srvnamesiz(len);
pubflag = nfs_ispublicfh(fhp);
nd.ni_cnd.cn_cred = cred;
nd.ni_cnd.cn_nameiop = LOOKUP;
nd.ni_cnd.cn_flags = LOCKLEAF | SAVESTART;
error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
&dirp, procp, (nfsd->nd_flag & ND_KERBAUTH));
&dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), pubflag);
if (!error && pubflag) {
if (nd.ni_vp->v_type == VDIR && nfs_pub.np_index != NULL) {
/*
* Setup call to lookup() to see if we can find
* the index file. Arguably, this doesn't belong
* in a kernel.. Ugh.
*/
ind = nd;
VOP_UNLOCK(nd.ni_vp, 0, procp);
ind.ni_pathlen = strlen(nfs_pub.np_index);
ind.ni_cnd.cn_nameptr = ind.ni_cnd.cn_pnbuf =
nfs_pub.np_index;
ind.ni_startdir = nd.ni_vp;
VREF(ind.ni_startdir);
error = lookup(&ind);
if (!error) {
/*
* Found an index file. Get rid of
* the old references.
*/
if (dirp)
vrele(dirp);
dirp = nd.ni_vp;
vrele(nd.ni_startdir);
ndp = &ind;
} else
error = 0;
}
/*
* If the public filehandle was used, check that this lookup
* didn't result in a filehandle outside the publicly exported
* filesystem.
*/
if (!error && ndp->ni_vp->v_mount != nfs_pub.np_mount) {
vput(nd.ni_vp);
error = EPERM;
}
}
if (dirp) {
if (v3)
dirattr_ret = VOP_GETATTR(dirp, &dirattr, cred,
procp);
vrele(dirp);
}
if (error) {
nfsm_reply(NFSX_POSTOPATTR(v3));
nfsm_srvpostop_attr(dirattr_ret, &dirattr);
return (0);
}
nqsrv_getl(nd.ni_startdir, ND_READ);
vrele(nd.ni_startdir);
nqsrv_getl(ndp->ni_startdir, ND_READ);
vrele(ndp->ni_startdir);
FREE(nd.ni_cnd.cn_pnbuf, M_NAMEI);
vp = nd.ni_vp;
vp = ndp->ni_vp;
bzero((caddr_t)fhp, sizeof(nfh));
fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
error = VFS_VPTOFH(vp, &fhp->fh_fid);
@ -491,7 +537,7 @@ nfsrv_readlink(nfsd, slp, procp, mrq)
uiop->uio_segflg = UIO_SYSSPACE;
uiop->uio_procp = (struct proc *)0;
if (error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
&rdonly, (nfsd->nd_flag & ND_KERBAUTH))) {
&rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE)) {
m_freem(mp3);
nfsm_reply(2 * NFSX_UNSIGNED);
nfsm_srvpostop_attr(1, (struct vattr *)0);
@ -574,7 +620,7 @@ nfsrv_read(nfsd, slp, procp, mrq)
}
nfsm_srvstrsiz(reqlen, NFS_SRVMAXDATA(nfsd));
if (error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
&rdonly, (nfsd->nd_flag & ND_KERBAUTH))) {
&rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE)) {
nfsm_reply(2 * NFSX_UNSIGNED);
nfsm_srvpostop_attr(1, (struct vattr *)0);
return (0);
@ -788,7 +834,7 @@ nfsrv_write(nfsd, slp, procp, mrq)
return (0);
}
if (error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
&rdonly, (nfsd->nd_flag & ND_KERBAUTH))) {
&rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE)) {
nfsm_reply(2 * NFSX_UNSIGNED);
nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
return (0);
@ -1066,7 +1112,7 @@ nfsrv_writegather(ndp, slp, procp, mrq)
v3 = (nfsd->nd_flag & ND_NFSV3);
forat_ret = aftat_ret = 1;
error = nfsrv_fhtovp(&nfsd->nd_fh, 1, &vp, cred, slp,
nfsd->nd_nam, &rdonly, (nfsd->nd_flag & ND_KERBAUTH));
nfsd->nd_nam, &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
if (!error) {
if (v3)
forat_ret = VOP_GETATTR(vp, &forat, cred, procp);
@ -1342,7 +1388,7 @@ nfsrv_create(nfsd, slp, procp, mrq)
nd.ni_cnd.cn_nameiop = CREATE;
nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART;
error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
&dirp, procp, (nfsd->nd_flag & ND_KERBAUTH));
&dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
if (dirp) {
if (v3)
dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
@ -1574,7 +1620,7 @@ nfsrv_mknod(nfsd, slp, procp, mrq)
nd.ni_cnd.cn_nameiop = CREATE;
nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART;
error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
&dirp, procp, (nfsd->nd_flag & ND_KERBAUTH));
&dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
if (dirp)
dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred, procp);
if (error) {
@ -1723,7 +1769,7 @@ nfsrv_remove(nfsd, slp, procp, mrq)
nd.ni_cnd.cn_nameiop = DELETE;
nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
&dirp, procp, (nfsd->nd_flag & ND_KERBAUTH));
&dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
if (dirp) {
if (v3)
dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
@ -1822,7 +1868,7 @@ nfsrv_rename(nfsd, slp, procp, mrq)
fromnd.ni_cnd.cn_nameiop = DELETE;
fromnd.ni_cnd.cn_flags = WANTPARENT | SAVESTART;
error = nfs_namei(&fromnd, ffhp, len, slp, nam, &md,
&dpos, &fdirp, procp, (nfsd->nd_flag & ND_KERBAUTH));
&dpos, &fdirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
if (fdirp) {
if (v3)
fdirfor_ret = VOP_GETATTR(fdirp, &fdirfor, cred,
@ -1848,7 +1894,7 @@ nfsrv_rename(nfsd, slp, procp, mrq)
tond.ni_cnd.cn_nameiop = RENAME;
tond.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART;
error = nfs_namei(&tond, tfhp, len2, slp, nam, &md,
&dpos, &tdirp, procp, (nfsd->nd_flag & ND_KERBAUTH));
&dpos, &tdirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
if (tdirp) {
if (v3)
tdirfor_ret = VOP_GETATTR(tdirp, &tdirfor, cred,
@ -2014,7 +2060,7 @@ nfsrv_link(nfsd, slp, procp, mrq)
nfsm_srvmtofh(dfhp);
nfsm_srvnamesiz(len);
if (error = nfsrv_fhtovp(fhp, FALSE, &vp, cred, slp, nam,
&rdonly, (nfsd->nd_flag & ND_KERBAUTH))) {
&rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE)) {
nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
nfsm_srvpostop_attr(getret, &at);
nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
@ -2028,7 +2074,7 @@ nfsrv_link(nfsd, slp, procp, mrq)
nd.ni_cnd.cn_nameiop = CREATE;
nd.ni_cnd.cn_flags = LOCKPARENT;
error = nfs_namei(&nd, dfhp, len, slp, nam, &md, &dpos,
&dirp, procp, (nfsd->nd_flag & ND_KERBAUTH));
&dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
if (dirp) {
if (v3)
dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
@ -2122,7 +2168,7 @@ nfsrv_symlink(nfsd, slp, procp, mrq)
nd.ni_cnd.cn_nameiop = CREATE;
nd.ni_cnd.cn_flags = LOCKPARENT | SAVESTART;
error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
&dirp, procp, (nfsd->nd_flag & ND_KERBAUTH));
&dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
if (dirp) {
if (v3)
dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
@ -2264,7 +2310,7 @@ nfsrv_mkdir(nfsd, slp, procp, mrq)
nd.ni_cnd.cn_nameiop = CREATE;
nd.ni_cnd.cn_flags = LOCKPARENT;
error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
&dirp, procp, (nfsd->nd_flag & ND_KERBAUTH));
&dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
if (dirp) {
if (v3)
dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
@ -2377,7 +2423,7 @@ nfsrv_rmdir(nfsd, slp, procp, mrq)
nd.ni_cnd.cn_nameiop = DELETE;
nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
&dirp, procp, (nfsd->nd_flag & ND_KERBAUTH));
&dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
if (dirp) {
if (v3)
dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
@ -2526,7 +2572,7 @@ nfsrv_readdir(nfsd, slp, procp, mrq)
siz = xfer;
fullsiz = siz;
if (error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
&rdonly, (nfsd->nd_flag & ND_KERBAUTH))) {
&rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE)) {
nfsm_reply(NFSX_UNSIGNED);
nfsm_srvpostop_attr(getret, &at);
return (0);
@ -2790,7 +2836,7 @@ nfsrv_readdirplus(nfsd, slp, procp, mrq)
siz = xfer;
fullsiz = siz;
if (error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
&rdonly, (nfsd->nd_flag & ND_KERBAUTH))) {
&rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE)) {
nfsm_reply(NFSX_UNSIGNED);
nfsm_srvpostop_attr(getret, &at);
return (0);
@ -3095,7 +3141,7 @@ nfsrv_commit(nfsd, slp, procp, mrq)
tl += 2;
cnt = fxdr_unsigned(int, *tl);
if (error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
&rdonly, (nfsd->nd_flag & ND_KERBAUTH))) {
&rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE)) {
nfsm_reply(2 * NFSX_UNSIGNED);
nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
return (0);
@ -3151,7 +3197,7 @@ nfsrv_statfs(nfsd, slp, procp, mrq)
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
if (error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
&rdonly, (nfsd->nd_flag & ND_KERBAUTH))) {
&rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE)) {
nfsm_reply(NFSX_UNSIGNED);
nfsm_srvpostop_attr(getret, &at);
return (0);
@ -3226,7 +3272,7 @@ nfsrv_fsinfo(nfsd, slp, procp, mrq)
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
if (error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
&rdonly, (nfsd->nd_flag & ND_KERBAUTH))) {
&rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE)) {
nfsm_reply(NFSX_UNSIGNED);
nfsm_srvpostop_attr(getret, &at);
return (0);
@ -3297,7 +3343,7 @@ nfsrv_pathconf(nfsd, slp, procp, mrq)
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
if (error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
&rdonly, (nfsd->nd_flag & ND_KERBAUTH))) {
&rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE)) {
nfsm_reply(NFSX_UNSIGNED);
nfsm_srvpostop_attr(getret, &at);
return (0);

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_subs.c 8.3 (Berkeley) 1/4/94
* $Id: nfs_subs.c,v 1.37 1997/02/22 09:42:41 peter Exp $
* $Id: nfs_subs.c,v 1.38 1997/04/04 17:49:29 dfr Exp $
*/
/*
@ -53,6 +53,7 @@
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/malloc.h>
#include <sys/dirent.h>
#ifdef VFS_LKM
#include <sys/sysent.h>
#include <sys/syscall.h>
@ -560,6 +561,8 @@ extern int nfssvc(struct proc *, struct nfssvc_args *, int *);
LIST_HEAD(nfsnodehashhead, nfsnode);
int nfs_webnamei __P((struct nameidata *, struct vnode *, struct proc *));
/*
* Create the header for an rpc request packet
* The hsiz is the size of the rest of the nfs request header.
@ -1412,10 +1415,16 @@ nfs_getattrcache(vp, vaper)
#ifndef NFS_NOSERVER
/*
* Set up nameidata for a lookup() call and do it
* Set up nameidata for a lookup() call and do it.
*
* If pubflag is set, this call is done for a lookup operation on the
* public filehandle. In that case we allow crossing mountpoints and
* absolute pathnames. However, the caller is expected to check that
* the lookup result is within the public fs, and deny access if
* it is not.
*/
int
nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, retdirp, p, kerbflag)
nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, retdirp, p, kerbflag, pubflag)
register struct nameidata *ndp;
fhandle_t *fhp;
int len;
@ -1425,13 +1434,15 @@ nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, retdirp, p, kerbflag)
caddr_t *dposp;
struct vnode **retdirp;
struct proc *p;
int kerbflag;
int kerbflag, pubflag;
{
register int i, rem;
register struct mbuf *md;
register char *fromcp, *tocp;
register char *fromcp, *tocp, *cp;
struct iovec aiov;
struct uio auio;
struct vnode *dp;
int error, rdonly;
int error, rdonly, linklen;
struct componentname *cnp = &ndp->ni_cnd;
*retdirp = (struct vnode *)0;
@ -1455,7 +1466,7 @@ nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, retdirp, p, kerbflag)
fromcp = mtod(md, caddr_t);
rem = md->m_len;
}
if (*fromcp == '\0' || *fromcp == '/') {
if (*fromcp == '\0' || (!pubflag && *fromcp == '/')) {
error = EACCES;
goto out;
}
@ -1473,55 +1484,170 @@ nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, retdirp, p, kerbflag)
else if (error = nfs_adv(mdp, dposp, len, rem))
goto out;
}
ndp->ni_pathlen = tocp - cnp->cn_pnbuf;
cnp->cn_nameptr = cnp->cn_pnbuf;
/*
* Extract and set starting directory.
*/
if (error = nfsrv_fhtovp(fhp, FALSE, &dp, ndp->ni_cnd.cn_cred, slp,
nam, &rdonly, kerbflag))
error = nfsrv_fhtovp(fhp, FALSE, &dp, ndp->ni_cnd.cn_cred, slp,
nam, &rdonly, kerbflag, pubflag);
if (error)
goto out;
if (dp->v_type != VDIR) {
vrele(dp);
error = ENOTDIR;
goto out;
}
VREF(dp);
*retdirp = dp;
ndp->ni_startdir = dp;
if (rdonly)
cnp->cn_flags |= (NOCROSSMOUNT | RDONLY);
else
cnp->cn_flags |= NOCROSSMOUNT;
cnp->cn_flags |= RDONLY;
if (pubflag) {
/*
* Oh joy. For WebNFS, handle those pesky '%' escapes,
* and the 'native path' indicator.
*/
MALLOC(cp, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
fromcp = cnp->cn_pnbuf;
tocp = cp;
if ((unsigned char)*fromcp >= WEBNFS_SPECCHAR_START) {
switch ((unsigned char)*fromcp) {
case WEBNFS_NATIVE_CHAR:
/*
* 'Native' path for us is the same
* as a path according to the NFS spec,
* just skip the escape char.
*/
fromcp++;
break;
/*
* More may be added in the future, range 0x80-0xff
*/
default:
error = EIO;
FREE(cp, M_NAMEI);
goto out;
}
}
/*
* Translate the '%' escapes, URL-style.
*/
while (*fromcp != '\0') {
if (*fromcp == WEBNFS_ESC_CHAR) {
if (fromcp[1] != '\0' && fromcp[2] != '\0') {
fromcp++;
*tocp++ = HEXSTRTOI(fromcp);
fromcp += 2;
continue;
} else {
error = ENOENT;
FREE(cp, M_NAMEI);
goto out;
}
} else
*tocp++ = *fromcp++;
}
*tocp = '\0';
FREE(cnp->cn_pnbuf, M_NAMEI);
cnp->cn_pnbuf = cp;
}
ndp->ni_pathlen = (tocp - cnp->cn_pnbuf) + 1;
ndp->ni_segflg = UIO_SYSSPACE;
if (pubflag) {
ndp->ni_rootdir = rootvnode;
ndp->ni_loopcnt = 0;
if (cnp->cn_pnbuf[0] == '/')
dp = rootvnode;
} else {
cnp->cn_flags |= NOCROSSMOUNT;
}
cnp->cn_proc = p;
VREF(dp);
for (;;) {
cnp->cn_nameptr = cnp->cn_pnbuf;
ndp->ni_startdir = dp;
/*
* And call lookup() to do the real work
*/
cnp->cn_proc = p;
if (error = lookup(ndp))
goto out;
break;
/*
* Check for encountering a symbolic link
*/
if (cnp->cn_flags & ISSYMLINK) {
if ((cnp->cn_flags & ISSYMLINK) == 0) {
nfsrv_object_create(ndp->ni_vp);
if (cnp->cn_flags & (SAVENAME | SAVESTART)) {
cnp->cn_flags |= HASBUF;
return (0);
}
break;
} else {
if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1)
vput(ndp->ni_dvp);
else
VOP_UNLOCK(ndp->ni_dvp, 0, p);
if (!pubflag) {
vrele(ndp->ni_dvp);
vput(ndp->ni_vp);
ndp->ni_vp = NULL;
error = EINVAL;
break;
}
if (ndp->ni_loopcnt++ >= MAXSYMLINKS) {
error = ELOOP;
break;
}
if (ndp->ni_pathlen > 0)
MALLOC(cp, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
else
cp = cnp->cn_pnbuf;
aiov.iov_base = cp;
aiov.iov_len = MAXPATHLEN;
auio.uio_iov = &aiov;
auio.uio_iovcnt = 1;
auio.uio_offset = 0;
auio.uio_rw = UIO_READ;
auio.uio_segflg = UIO_SYSSPACE;
auio.uio_procp = (struct proc *)0;
auio.uio_resid = MAXPATHLEN;
error = VOP_READLINK(ndp->ni_vp, &auio, cnp->cn_cred);
if (error) {
badlink:
if (ndp->ni_pathlen > 1)
FREE(cp, M_NAMEI);
break;
}
linklen = MAXPATHLEN - auio.uio_resid;
if (linklen == 0) {
error = ENOENT;
goto badlink;
}
if (linklen + ndp->ni_pathlen >= MAXPATHLEN) {
error = ENAMETOOLONG;
goto badlink;
}
if (ndp->ni_pathlen > 1) {
bcopy(ndp->ni_next, cp + linklen, ndp->ni_pathlen);
FREE(cnp->cn_pnbuf, M_NAMEI);
cnp->cn_pnbuf = cp;
} else
cnp->cn_pnbuf[linklen] = '\0';
ndp->ni_pathlen += linklen;
vput(ndp->ni_vp);
ndp->ni_vp = NULL;
error = EINVAL;
goto out;
}
nfsrv_object_create(ndp->ni_vp);
/*
* Check for saved name request
*/
if (cnp->cn_flags & (SAVENAME | SAVESTART)) {
cnp->cn_flags |= HASBUF;
return (0);
dp = ndp->ni_dvp;
/*
* Check if root directory should replace current directory.
*/
if (cnp->cn_pnbuf[0] == '/') {
vrele(dp);
dp = ndp->ni_rootdir;
VREF(dp);
}
}
}
out:
FREE(cnp->cn_pnbuf, M_NAMEI);
return (error);
@ -1700,7 +1826,7 @@ nfsm_srvfattr(nfsd, vap, fp)
* - if not lockflag unlock it with VOP_UNLOCK()
*/
int
nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag)
nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag, pubflag)
fhandle_t *fhp;
int lockflag;
struct vnode **vpp;
@ -1709,6 +1835,7 @@ nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag)
struct mbuf *nam;
int *rdonlyp;
int kerbflag;
int pubflag;
{
struct proc *p = curproc; /* XXX */
register struct mount *mp;
@ -1717,6 +1844,13 @@ nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag)
int error, exflags;
*vpp = (struct vnode *)0;
if (nfs_ispublicfh(fhp)) {
if (!pubflag || !nfs_pub.np_valid)
return (ESTALE);
fhp = &nfs_pub.np_handle;
}
mp = vfs_getvfs(&fhp->fh_fsid);
if (!mp)
return (ESTALE);
@ -1752,6 +1886,25 @@ nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag)
return (0);
}
/*
* WebNFS: check if a filehandle is a public filehandle. For v3, this
* means a length of 0, for v2 it means all zeroes. nfsm_srvmtofh has
* transformed this to all zeroes in both cases, so check for it.
*/
int
nfs_ispublicfh(fhp)
fhandle_t *fhp;
{
char *cp = (char *)fhp;
int i;
for (i = 0; i < NFSX_V3FH; i++)
if (*cp++ != 0)
return (FALSE);
return (TRUE);
}
#endif /* NFS_NOSERVER */
/*
* This function compares two net addresses by family and returns TRUE

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_syscalls.c 8.5 (Berkeley) 3/30/95
* $Id: nfs_syscalls.c,v 1.24 1997/05/13 17:25:44 dfr Exp $
* $Id: nfs_syscalls.c,v 1.25 1997/06/25 21:07:26 tegge Exp $
*/
#include <sys/param.h>
@ -1129,7 +1129,8 @@ nfsrv_init(terminating)
free((caddr_t)slp, M_NFSSVC);
}
nfsrv_cleancache(); /* And clear out server cache */
}
} else
nfs_pub.np_valid = 0;
TAILQ_INIT(&nfssvc_sockhead);
nfssvc_sockhead_flag &= ~SLP_INIT;

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfsm_subs.h 8.2 (Berkeley) 3/30/95
* $Id$
* $Id: nfsm_subs.h,v 1.12 1997/02/22 09:42:48 peter Exp $
*/
@ -363,18 +363,24 @@ struct mbuf *nfsm_rpchead __P((struct ucred *cr, int nmflag, int procid,
} }
#define nfsm_srvmtofh(f) \
{ if (nfsd->nd_flag & ND_NFSV3) { \
{ int fhlen = NFSX_V3FH; \
if (nfsd->nd_flag & ND_NFSV3) { \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
if (fxdr_unsigned(int, *tl) != NFSX_V3FH) { \
fhlen = fxdr_unsigned(int, *tl); \
if (fhlen == 0) { \
bzero((caddr_t)(f), NFSX_V3FH); \
} else if (fhlen != NFSX_V3FH) { \
error = EBADRPC; \
nfsm_reply(0); \
} \
} \
nfsm_dissect(tl, u_long *, NFSX_V3FH); \
bcopy((caddr_t)tl, (caddr_t)(f), NFSX_V3FH); \
if ((nfsd->nd_flag & ND_NFSV3) == 0) \
nfsm_adv(NFSX_V2FH - NFSX_V3FH); \
}
if (fhlen != 0) { \
nfsm_dissect(tl, u_long *, NFSX_V3FH); \
bcopy((caddr_t)tl, (caddr_t)(f), NFSX_V3FH); \
if ((nfsd->nd_flag & ND_NFSV3) == 0) \
nfsm_adv(NFSX_V2FH - NFSX_V3FH); \
} \
}
#define nfsm_clget \
if (bp >= be) { \

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs.h 8.4 (Berkeley) 5/1/95
* $Id: nfs.h,v 1.27 1997/05/19 14:36:46 dfr Exp $
* $Id: nfs.h,v 1.28 1997/06/03 17:22:45 dfr Exp $
*/
#ifndef _NFS_NFS_H_
@ -522,6 +522,30 @@ extern int nfsd_head_flag;
!bcmp((caddr_t)&(o)->nd_cr, (caddr_t)&(n)->nd_cr, \
sizeof (struct ucred)))
/*
* Defines for WebNFS
*/
#define WEBNFS_ESC_CHAR '%'
#define WEBNFS_SPECCHAR_START 0x80
#define WEBNFS_NATIVE_CHAR 0x80
/*
* ..
* Possibly more here in the future.
*/
/*
* Macro for converting escape characters in WebNFS pathnames.
* Should really be in libkern.
*/
#define HEXTOC(c) \
((c) >= 'a' ? ((c) - ('a' - 10)) : \
((c) >= 'A' ? ((c) - ('A' - 10)) : ((c) - '0')))
#define HEXSTRTOI(p) \
((HEXTOC(p[0]) << 4) + HEXTOC(p[1]))
#ifdef NFS_DEBUG
extern int nfs_debug;
@ -564,7 +588,7 @@ void nfsm_srvpostopattr __P((struct nfsrv_descript *,int,struct vattr *,struct m
int netaddr_match __P((int,union nethostaddr *,struct mbuf *));
int nfs_request __P((struct vnode *,struct mbuf *,int,struct proc *,struct ucred *,struct mbuf **,struct mbuf **,caddr_t *));
int nfs_loadattrcache __P((struct vnode **,struct mbuf **,caddr_t *,struct vattr *));
int nfs_namei __P((struct nameidata *,fhandle_t *,int,struct nfssvc_sock *,struct mbuf *,struct mbuf **,caddr_t *,struct vnode **,struct proc *,int));
int nfs_namei __P((struct nameidata *,fhandle_t *,int,struct nfssvc_sock *,struct mbuf *,struct mbuf **,caddr_t *,struct vnode **,struct proc *,int,int));
void nfsm_adj __P((struct mbuf *,int,int));
int nfsm_mbuftouio __P((struct mbuf **,struct uio *,int,caddr_t *));
void nfsrv_initcache __P((void));
@ -606,7 +630,10 @@ int nfsrv_create __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
struct proc *procp, struct mbuf **mrq));
int nfsrv_fhtovp __P((fhandle_t *,int,struct vnode **,
struct ucred *,struct nfssvc_sock *,struct mbuf *,
int *,int));
int *,int,int));
int nfsrv_setpublicfs __P((struct mount *, struct netexport *,
struct export_args *));
int nfs_ispublicfh __P((fhandle_t *));
int nfsrv_fsinfo __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
struct proc *procp, struct mbuf **mrq));
int nfsrv_getattr __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,