]> git.decadent.org.uk Git - nfs-utils.git/blobdiff - utils/mountd/mountd.c
new "mountpoint" export option.
[nfs-utils.git] / utils / mountd / mountd.c
index 971e4f4e2be8ca774328aed24c921bdea4f7edcc..3769c924d2d22a0e973e19a202d2d31833f40057 100644 (file)
 #include "mountd.h"
 #include "rpcmisc.h"
 
+extern void    cache_open(void);
+extern struct nfs_fh_len *cache_get_filehandle(nfs_export *exp, int len, char *p);
+extern void cache_export(nfs_export *exp);
+
+extern void my_svc_run(void);
+
 static void            usage(const char *, int exitcode);
 static exports         get_exportlist(void);
 static struct nfs_fh_len *get_rootfh(struct svc_req *, dirpath *, int *, int v3);
 
+int new_cache = 0;
+
 static struct option longopts[] =
 {
        { "foreground", 0, 0, 'F' },
@@ -182,7 +190,7 @@ mount_pathconf_2_svc(struct svc_req *rqstp, dirpath *path, ppathcnf *res)
        }
 
        /* Now authenticate the intruder... */
-       if (!(exp = auth_authenticate("mount", sin, p))) {
+       if (!(exp = auth_authenticate("pathconf", sin, p))) {
                return 1;
        } else if (stat(p, &stb) < 0) {
                xlog(L_WARNING, "can't stat exported dir %s: %s",
@@ -234,7 +242,7 @@ get_rootfh(struct svc_req *rqstp, dirpath *path, int *error, int v3)
 {
        struct sockaddr_in *sin =
                (struct sockaddr_in *) svc_getcaller(rqstp->rq_xprt);
-       struct stat     stb;
+       struct stat     stb, estb;
        nfs_export      *exp;
        char            rpath[MAXPATHLEN+1];
        char            *p = *path;
@@ -264,6 +272,37 @@ get_rootfh(struct svc_req *rqstp, dirpath *path, int *error, int v3)
        } else if (!S_ISDIR(stb.st_mode) && !S_ISREG(stb.st_mode)) {
                xlog(L_WARNING, "%s is not a directory or regular file", p);
                *error = NFSERR_NOTDIR;
+       } else if (stat(exp->m_export.e_path, &estb) < 0) {
+               xlog(L_WARNING, "can't stat export point %s: %s",
+                    p, strerror(errno));
+               *error = NFSERR_NOENT;
+       } else if (estb.st_dev != stb.st_dev
+                  /* && (!new_cache || !(exp->m_export.e_flags & NFSEXP_CROSSMNT)) */
+               ) {
+               xlog(L_WARNING, "request to export directory %s below nearest filesystem %s",
+                    p, exp->m_export.e_path);
+               *error = NFSERR_ACCES;
+       } else if (exp->m_export.e_mountpoint &&
+                  !is_mountpoint(exp->m_export.e_mountpoint[0]?
+                                 exp->m_export.e_mountpoint:
+                                 exp->m_export.e_path)) {
+               xlog(L_WARNING, "request to export an unmounted filesystem: %s",
+                    p);
+               *error = NFSERR_NOENT;
+       } else if (new_cache) {
+               /* This will be a static private nfs_export with just one
+                * address.  We feed it to kernel then extract the filehandle,
+                * 
+                */
+               struct nfs_fh_len  *fh;
+
+               cache_export(exp);
+               fh = cache_get_filehandle(exp, v3?64:32, p);
+               if (fh == NULL) 
+                       *error = NFSERR_ACCES;
+               else
+                       *error = NFS_OK;
+               return fh;
        } else {
                struct nfs_fh_len  *fh;
 
@@ -491,6 +530,10 @@ main(int argc, char **argv)
                        (void) close(fd);
        }
 
+       new_cache = check_new_cache();
+       if (new_cache)
+               cache_open();
+
        if (nfs_version & 0x1)
                rpc_init("mountd", MOUNTPROG, MOUNTVERS,
                         mount_dispatch, port);
@@ -529,7 +572,7 @@ main(int argc, char **argv)
                xlog_background();
        }
 
-       svc_run();
+       my_svc_run();
 
        xlog(L_ERROR, "Ack! Gack! svc_run returned!\n");
        exit(1);