From fde2ae7794047a698feeaf17963d690a1e660a80 Mon Sep 17 00:00:00 2001 From: Steve Dickson Date: Mon, 26 Jun 2006 15:23:19 +1000 Subject: [PATCH] Add support for suppressing different NFS versions. e.g. -N 2 means that NFSv2 won't be supported, just v3 and v4 (if the kernel supports them). --- support/include/nfs/nfs.h | 7 ++++++ support/include/nfslib.h | 2 +- support/nfs/nfssvc.c | 33 ++++++++++++++++++++++++++- utils/nfsd/nfsd.c | 48 ++++++++++++++++++++++++++++++++------- utils/nfsd/nfsd.man | 11 +++++++-- 5 files changed, 89 insertions(+), 12 deletions(-) diff --git a/support/include/nfs/nfs.h b/support/include/nfs/nfs.h index c7fc42c..2cf6857 100644 --- a/support/include/nfs/nfs.h +++ b/support/include/nfs/nfs.h @@ -10,6 +10,9 @@ #define NFS3_FHSIZE 64 #define NFS_FHSIZE 32 +#define NFSD_MINVERS 2 +#define NFSD_MAXVERS 4 + struct nfs_fh_len { int fh_size; u_int8_t fh_handle[NFS3_FHSIZE]; @@ -40,7 +43,11 @@ struct nfs_fh_old { #define NFSCTL_LOCKD 0x10000 #define LOCKDCTL_SVC NFSCTL_LOCKD +#define NFSCTL_VERUNSET(_cltbits, _v) ((_cltbits) &= ~(1 << ((_v) - 1))) + +#define NFSCTL_VERISSET(_cltbits, _v) ((_cltbits) & (1 << ((_v) - 1))) +#define NFSCTL_ALLBITS (~0) /* SVC */ struct nfsctl_svc { diff --git a/support/include/nfslib.h b/support/include/nfslib.h index 8c83262..50892e2 100644 --- a/support/include/nfslib.h +++ b/support/include/nfslib.h @@ -120,7 +120,7 @@ int wildmat(char *text, char *pattern); * nfsd library functions. */ int nfsctl(int, struct nfsctl_arg *, union nfsctl_res *); -int nfssvc(int port, int nrservs); +int nfssvc(int port, int nrservs, unsigned int versbits); int nfsaddclient(struct nfsctl_client *clp); int nfsdelclient(struct nfsctl_client *clp); int nfsexport(struct nfsctl_export *exp); diff --git a/support/nfs/nfssvc.c b/support/nfs/nfssvc.c index 38240a0..c51ace1 100644 --- a/support/nfs/nfssvc.c +++ b/support/nfs/nfssvc.c @@ -12,15 +12,46 @@ #include #include +#include +#include #include "nfslib.h" +static void +nfssvc_versbits(unsigned int ctlbits) +{ + int fd, n, off; + char buf[BUFSIZ], *ptr; + + ptr = buf; + off = 0; + fd = open("/proc/fs/nfsd/versions", O_WRONLY); + if (fd < 0) + return; + + for (n = NFSD_MINVERS; n <= NFSD_MAXVERS; n++) { + if (NFSCTL_VERISSET(ctlbits, n)) + off += snprintf(ptr+off, BUFSIZ - off, "+%d ", n); + else + off += snprintf(ptr+off, BUFSIZ - off, "-%d ", n); + } + snprintf(ptr+off, BUFSIZ - off, "\n"); + if (write(fd, buf, strlen(buf)) != strlen(buf)) { + syslog(LOG_ERR, "nfssvc: Setting version failed: errno %d (%s)", + errno, strerror(errno)); + } + close(fd); + + return; +} int -nfssvc(int port, int nrservs) +nfssvc(int port, int nrservs, unsigned int versbits) { struct nfsctl_arg arg; int fd; + nfssvc_versbits(versbits); + fd = open("/proc/fs/nfsd/threads", O_WRONLY); if (fd < 0) fd = open("/proc/fs/nfs/threads", O_WRONLY); diff --git a/utils/nfsd/nfsd.c b/utils/nfsd/nfsd.c index 05506ee..fa6ee71 100644 --- a/utils/nfsd/nfsd.c +++ b/utils/nfsd/nfsd.c @@ -24,10 +24,18 @@ static void usage(const char *); +static struct option longopts[] = +{ + { "help", 0, 0, 'h' }, + { "no-nfs-version", 1, 0, 'N' }, + { NULL, 0, 0, 0 } +}; +unsigned int versbits = NFSCTL_ALLBITS; + int main(int argc, char **argv) { - int count = 1, c, error, port, fd; + int count = 1, c, error, port, fd, found_one; struct servent *ent; ent = getservbyname ("nfs", "udp"); @@ -36,7 +44,7 @@ main(int argc, char **argv) else port = 2049; - while ((c = getopt(argc, argv, "hp:P:")) != EOF) { + while ((c = getopt_long(argc, argv, "hN:p:P:", longopts, NULL)) != EOF) { switch(c) { case 'P': /* XXX for nfs-server compatibility */ case 'p': @@ -47,12 +55,36 @@ main(int argc, char **argv) usage(argv [0]); } break; + case 'N': + switch((c = atoi(optarg))) { + case 2: + case 3: + case 4: + NFSCTL_VERUNSET(versbits, c); + break; + default: + fprintf(stderr, "%c: Unsupported version\n", c); + exit(1); + } break; - case 'h': default: + fprintf(stderr, "Invalid argument: '%c'\n", c); + case 'h': usage(argv[0]); } } + /* + * Do some sanity checking, if the ctlbits are set + */ + found_one = 0; + for (c = NFSD_MINVERS; c <= NFSD_MAXVERS; c++) { + if (NFSCTL_VERISSET(versbits, c)) + found_one = 1; + } + if (!found_one) { + fprintf(stderr, "no version specified\n"); + exit(1); + } if (chdir(NFS_STATEDIR)) { fprintf(stderr, "%s: chdir(%s) failed: %s\n", @@ -69,7 +101,6 @@ main(int argc, char **argv) count = 1; } } - /* KLUDGE ALERT: Some kernels let nfsd kernel threads inherit open files from the program that spawns them (i.e. us). So close @@ -84,9 +115,9 @@ main(int argc, char **argv) } closeall(3); - if ((error = nfssvc(port, count)) < 0) { + openlog("nfsd", LOG_PID, LOG_DAEMON); + if ((error = nfssvc(port, count, versbits)) < 0) { int e = errno; - openlog("nfsd", LOG_PID, LOG_DAEMON); syslog(LOG_ERR, "nfssvc: %s", strerror(e)); closelog(); } @@ -97,7 +128,8 @@ main(int argc, char **argv) static void usage(const char *prog) { - fprintf(stderr, "usage:\n" - "%s nrservs\n", prog); + fprintf(stderr, "Usage:\n" + "%s [-p|-P|--port port] [-N|--no-nfs-version version ] nrservs\n", + prog); exit(2); } diff --git a/utils/nfsd/nfsd.man b/utils/nfsd/nfsd.man index a890ea6..d175d11 100644 --- a/utils/nfsd/nfsd.man +++ b/utils/nfsd/nfsd.man @@ -6,7 +6,7 @@ .SH NAME rpc.nfsd \- NFS server process .SH SYNOPSIS -.BI "/usr/sbin/rpc.nfsd [-p " port "] " nproc +.BI "/usr/sbin/rpc.nfsd [" options "]" " "nproc .SH DESCRIPTION The .B rpc.nfsd @@ -22,11 +22,18 @@ server provides an ancillary service needed to satisfy mount requests by NFS clients. .SH OPTIONS .TP -.BI \-p " port" +.B \-p " or " \-\-port port specify a diferent port to listen on for NFS requests. By default, .B rpc.nfsd will listen on port 2049. .TP +.B \-N " or " \-\-no-nfs-version vers +This option can be used to request that +.B rpc.nfsd +does not offer certain versions of NFS. The current version of +.B rpc.nfsd +can support both NFS version 2,3 and the newer version 4. +.TP .I nproc specify the number of NFS server threads. By default, just one thread is started. However, for optimum performance several threads -- 2.39.5