Merge WebNFS changes from NetBSD.
Obtained from: NetBSD
This commit is contained in:
parent
5827e97390
commit
e775608178
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=27446
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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) { \
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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) { \
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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) { \
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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) { \
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user