X-Git-Url: https://git.decadent.org.uk/gitweb/?p=nfs-utils.git;a=blobdiff_plain;f=utils%2Fmountd%2Fmountd.c;h=8f6f9cb9d85d8ad69754a9db1bdbda2233feab76;hp=f785ef23e6a75a45727081c5a8d217595139812b;hb=b01c85ea978f15d313961724d9a64c8ae18b3766;hpb=a1c827e358e11fcf27e223ed45a54f6d328e78bc diff --git a/utils/mountd/mountd.c b/utils/mountd/mountd.c index f785ef2..8f6f9cb 100644 --- a/utils/mountd/mountd.c +++ b/utils/mountd/mountd.c @@ -24,10 +24,18 @@ #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' }, @@ -109,8 +117,14 @@ mount_umnt_1_svc(struct svc_req *rqstp, dirpath *argp, void *resp) if (!(exp = auth_authenticate("unmount", sin, p))) { return 1; } - mountlist_del(exp, p); - export_reset (exp); + if (new_cache) { + if (strcmp(inet_ntoa(exp->m_client->m_addrlist[0]), exp->m_client->m_hostname)) + mountlist_del(inet_ntoa(exp->m_client->m_addrlist[0]), exp->m_client->m_hostname); + mountlist_del(exp->m_client->m_hostname, p); + } else { + mountlist_del(exp->m_client->m_hostname, p); + export_reset (exp); + } return 1; } @@ -182,7 +196,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 +248,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 +278,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_CROSSMOUNT)) */ + ) { + 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; @@ -283,7 +328,7 @@ get_rootfh(struct svc_req *rqstp, dirpath *path, int *error, int v3) stb.st_dev, stb.st_ino); } if (fh != NULL) { - mountlist_add(exp, p); + mountlist_add(exp->m_client->m_hostname, p); *error = NFS_OK; export_reset (exp); return fh; @@ -392,14 +437,14 @@ main(int argc, char **argv) char *export_file = _PATH_EXPORTS; int foreground = 0; int port = 0; - int descriptors = 256; + int descriptors = 0; int c; struct sigaction sa; struct rlimit rlim; /* Parse the command line options and arguments. */ opterr = 0; - while ((c = getopt_long(argc, argv, "o:Fd:f:p:P:hN:V:v", longopts, NULL)) != EOF) + while ((c = getopt_long(argc, argv, "o:n:Fd:f:p:P:hN:V:v", longopts, NULL)) != EOF) switch (c) { case 'o': descriptors = atoi(optarg); @@ -459,19 +504,23 @@ main(int argc, char **argv) exit(1); } - if (getrlimit (RLIMIT_NOFILE, &rlim) != 0) { + if (getrlimit (RLIMIT_NOFILE, &rlim) != 0) fprintf(stderr, "%s: getrlimit (RLIMIT_NOFILE) failed: %s\n", - argv [0], strerror(errno)); - exit(1); - } - - rlim.rlim_cur = descriptors; - if (setrlimit (RLIMIT_NOFILE, &rlim) != 0) { - fprintf(stderr, "%s: setrlimit (RLIMIT_NOFILE) failed: %s\n", - argv [0], strerror(errno)); - exit(1); + argv [0], strerror(errno)); + else { + /* glibc sunrpc code dies if getdtablesize > FD_SETSIZE */ + if ((descriptors == 0 && rlim.rlim_cur > FD_SETSIZE) || + descriptors > FD_SETSIZE) + descriptors = FD_SETSIZE; + if (descriptors) { + rlim.rlim_cur = descriptors; + if (setrlimit (RLIMIT_NOFILE, &rlim) != 0) { + fprintf(stderr, "%s: setrlimit (RLIMIT_NOFILE) failed: %s\n", + argv [0], strerror(errno)); + exit(1); + } + } } - /* Initialize logging. */ /* xlog_open("mountd"); */ @@ -481,6 +530,7 @@ main(int argc, char **argv) sigaction(SIGHUP, &sa, NULL); sigaction(SIGINT, &sa, NULL); sigaction(SIGTERM, &sa, NULL); + sigaction(SIGPIPE, &sa, NULL); /* WARNING: the following works on Linux and SysV, but not BSD! */ sigaction(SIGCHLD, &sa, NULL); @@ -491,6 +541,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 +583,7 @@ main(int argc, char **argv) xlog_background(); } - svc_run(); + my_svc_run(); xlog(L_ERROR, "Ack! Gack! svc_run returned!\n"); exit(1);