diff options
Diffstat (limited to 'sys/nfsclient')
-rw-r--r-- | sys/nfsclient/nfs.h | 33 | ||||
-rw-r--r-- | sys/nfsclient/nfs_nfsiod.c | 5 | ||||
-rw-r--r-- | sys/nfsclient/nfs_subs.c | 221 | ||||
-rw-r--r-- | sys/nfsclient/nfsargs.h | 33 | ||||
-rw-r--r-- | sys/nfsclient/nfsm_subs.h | 22 | ||||
-rw-r--r-- | sys/nfsclient/nfsstats.h | 33 |
6 files changed, 294 insertions, 53 deletions
diff --git a/sys/nfsclient/nfs.h b/sys/nfsclient/nfs.h index 3521dae..528a366 100644 --- a/sys/nfsclient/nfs.h +++ b/sys/nfsclient/nfs.h @@ -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, diff --git a/sys/nfsclient/nfs_nfsiod.c b/sys/nfsclient/nfs_nfsiod.c index de07c23..0c46e28 100644 --- a/sys/nfsclient/nfs_nfsiod.c +++ b/sys/nfsclient/nfs_nfsiod.c @@ -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; diff --git a/sys/nfsclient/nfs_subs.c b/sys/nfsclient/nfs_subs.c index 572ccc2..105bc52 100644 --- a/sys/nfsclient/nfs_subs.c +++ b/sys/nfsclient/nfs_subs.c @@ -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; } + + if (rdonly) + 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); - *retdirp = dp; + + for (;;) { + cnp->cn_nameptr = cnp->cn_pnbuf; ndp->ni_startdir = dp; - if (rdonly) - cnp->cn_flags |= (NOCROSSMOUNT | RDONLY); - else - cnp->cn_flags |= NOCROSSMOUNT; /* * 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; - goto out; - } - - nfsrv_object_create(ndp->ni_vp); + vput(ndp->ni_vp); + ndp->ni_vp = NULL; + error = EINVAL; + break; + } - /* - * Check for saved name request - */ - if (cnp->cn_flags & (SAVENAME | SAVESTART)) { - cnp->cn_flags |= HASBUF; - return (0); + 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); + 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 diff --git a/sys/nfsclient/nfsargs.h b/sys/nfsclient/nfsargs.h index 3521dae..528a366 100644 --- a/sys/nfsclient/nfsargs.h +++ b/sys/nfsclient/nfsargs.h @@ -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, diff --git a/sys/nfsclient/nfsm_subs.h b/sys/nfsclient/nfsm_subs.h index c2677c8..e33be82 100644 --- a/sys/nfsclient/nfsm_subs.h +++ b/sys/nfsclient/nfsm_subs.h @@ -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) { \ diff --git a/sys/nfsclient/nfsstats.h b/sys/nfsclient/nfsstats.h index 3521dae..528a366 100644 --- a/sys/nfsclient/nfsstats.h +++ b/sys/nfsclient/nfsstats.h @@ -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, |