summaryrefslogtreecommitdiffstats
path: root/sys/nfsserver
diff options
context:
space:
mode:
authordfr <dfr@FreeBSD.org>1997-07-16 09:06:30 +0000
committerdfr <dfr@FreeBSD.org>1997-07-16 09:06:30 +0000
commitb627718fbd9e30033d07c3277899ab4726ac6b9b (patch)
tree8e1ab5384b1f019ad8b612a3fc1d51416baf1acd /sys/nfsserver
parent9b1c747b1bcc658b6cafea5e03c5c0f0b4cbb74f (diff)
downloadFreeBSD-src-b627718fbd9e30033d07c3277899ab4726ac6b9b.zip
FreeBSD-src-b627718fbd9e30033d07c3277899ab4726ac6b9b.tar.gz
Merge WebNFS changes from NetBSD.
Obtained from: NetBSD
Diffstat (limited to 'sys/nfsserver')
-rw-r--r--sys/nfsserver/nfs.h33
-rw-r--r--sys/nfsserver/nfs_serv.c106
-rw-r--r--sys/nfsserver/nfs_srvsubs.c221
-rw-r--r--sys/nfsserver/nfs_syscalls.c5
-rw-r--r--sys/nfsserver/nfsm_subs.h22
-rw-r--r--sys/nfsserver/nfsrvstats.h33
6 files changed, 340 insertions, 80 deletions
diff --git a/sys/nfsserver/nfs.h b/sys/nfsserver/nfs.h
index 3521dae..528a366 100644
--- a/sys/nfsserver/nfs.h
+++ b/sys/nfsserver/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/nfsserver/nfs_serv.c b/sys/nfsserver/nfs_serv.c
index f393986..e0770ac 100644
--- a/sys/nfsserver/nfs_serv.c
+++ b/sys/nfsserver/nfs_serv.c
@@ -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 @@ loop1:
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);
diff --git a/sys/nfsserver/nfs_srvsubs.c b/sys/nfsserver/nfs_srvsubs.c
index 572ccc2..105bc52 100644
--- a/sys/nfsserver/nfs_srvsubs.c
+++ b/sys/nfsserver/nfs_srvsubs.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/nfsserver/nfs_syscalls.c b/sys/nfsserver/nfs_syscalls.c
index de07c23..0c46e28 100644
--- a/sys/nfsserver/nfs_syscalls.c
+++ b/sys/nfsserver/nfs_syscalls.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/nfsserver/nfsm_subs.h b/sys/nfsserver/nfsm_subs.h
index c2677c8..e33be82 100644
--- a/sys/nfsserver/nfsm_subs.h
+++ b/sys/nfsserver/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/nfsserver/nfsrvstats.h b/sys/nfsserver/nfsrvstats.h
index 3521dae..528a366 100644
--- a/sys/nfsserver/nfsrvstats.h
+++ b/sys/nfsserver/nfsrvstats.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,
OpenPOWER on IntegriCloud