From: Greg Banks Date: Mon, 3 Jul 2006 04:21:48 +0000 (+1000) Subject: Merge branch 'master' of git://linux-nfs.org/nfs-utils X-Git-Tag: nfs-utils-1-0-9~30 X-Git-Url: https://git.decadent.org.uk/gitweb/?p=nfs-utils.git;a=commitdiff_plain;h=940c7c304d4a43c00c27529cdddc7c87db6eef87;hp=b90d201551aaa712c011c3d5de900fad714a26a6 Merge branch 'master' of git://linux-nfs.org/nfs-utils --- diff --git a/ChangeLog b/ChangeLog index 35de983..aec3014 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,187 @@ +commit 49b164d978ee6266df7ba0bd335cb34337e7c381 +Author: Steve Dickson +Date: Mon Jul 3 09:52:00 2006 +1000 + + Allow rpc.nfsd to suppress tcp or udp, and listen on a specific address. + + -T - will suppressing listening for TCP connection. + -U - will suppress UDP + -H host - will only listen on that local address + -p port - will listen on that port. + + This requires kernel patches which will hopefully be in 2.6.19 and possibly some + earlier test and vendor kernels. + +commit fde2ae7794047a698feeaf17963d690a1e660a80 +Author: Steve Dickson +Date: Mon Jun 26 15:23:19 2006 +1000 + + 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). + +commit 0523fd513c6baa8dbf45d1a7afea2044262aeb3d +Author: Neil Brown +Date: Fri Jun 23 17:10:56 2006 +1000 + + Further coverity related cleanups. + + Greg Banks suggested some variations, particularly improved + use of xmalloc/xstrdup functions. Thanks. + +commit 2e075a16da4963f54cd556403ca9e15a68de27fd +Author: Neil Brown +Date: Fri Jun 23 14:38:33 2006 +1000 + + Fix various issues discovered by Coverity + + Thanks to Michael Halcrow for finding them. + +commit ff42180930a444cea7f19e55e2cd2bfe6d3f108b +Author: Neil Brown +Date: Fri Jun 23 14:06:00 2006 +1000 + + Fix comment parsing (again) + + Bruce Fields noticed that I broke comment parsing... + + as xskip() is always called before xgettok(), that is the + best place to put xskipcomment and still maintain proper + semantics of xskip and xgettok. + +commit bec968578d97eabc63ae4a12bdeb2b33f40baec4 +Author: Amit Gud +Date: Thu Jun 22 12:51:04 2006 -0400 + + Change mount configure option to --enable-mount + + Change the configure option from --with-mount to --enable-mount. + + Signed-off-by: Amit Gud + Signed-off-by: Steve Dickson + +commit ceeffc1f76485b4084b2c61f4ff3c40e4f51c3b8 +Author: Amit Gud +Date: Thu Jun 22 12:49:24 2006 -0400 + + Merge nfsmount.x and mount.x into mount.x + + + Merge utils/mount/nfsmount.x and support/export/mount.x into support/export/mount.x. + + Signed-off-by: Amit Gud + Signed-off-by: Steve Dickson + +commit c2db41e8abb6ddc9d03a0c91c6db043fa0f85a8f +Author: Neil Brown +Date: Fri Jun 23 13:37:08 2006 +1000 + + Try to make sure that clientid used for NFSv4 is reliable. + + We need to give an IP address to identify this client to the + server. + The current code does a gethostbyname of the hostname. One + some systems this returns 127.0.0.1 or similar, which is not useful. + + Instead, use getsockname of the sock used to connect to the server + to confirm that the server is working. This gives the address on the + interface that was chosen to talk to that server, which is the + best address we can find (if there is a NAT in the way, it might + still not work, but in that case there is nothing we can do). + +commit 11d34d11153df198103a57291937ea9ff8b7356e +Author: Greg Banks +Date: Wed Jun 14 22:48:10 2006 +1000 + + multiple threads for mountd + + + How about the attached patch against nfs-utils tot? It + adds a -t option to set the number of forked workers. + Default is 1 thread, i.e. the old behaviour. + + I've verified that showmount -e, the Ogata mount client, + and a real mount from Linux and IRIX boxes work with and + without the new option. + + I've verified that you can manually kill any of the workers + without the portmap registration going away, that killing + all the workers causes the manager process to wake up and + unregister, and killing the manager process causes the + workers to be killed and portmap unregistered. + + I've verified that all the workers have file descriptors + for the udp socket and the tcp rendezvous socket, that + connections are balanced across all the workers if service + times are sufficiently long, and that performance is + improved by that parallelism, at least for small numbers + of threads. For example, with 60 parallel MOUNT calls + and a testing patch to make DNS lookups take 100 milliseconds + time to perform all mounts (averaged over 5 runs) is: + + num elapsed + threads time (sec) + ------ ---------- + 1 13.125 + 2 6.859 + 3 4.836 + 4 3.841 + 5 3.303 + 6 3.100 + 7 3.078 + 8 3.018 + + Greg. + -- + Greg Banks, R&D Software Engineer, SGI Australian Software Group. + I don't speak for SGI. + +commit db96d056578338dd1bb0371dc84638973c187ec6 +Author: Neil Brown +Date: Fri Jun 16 13:16:09 2006 +1000 + + Remove some temporary files that shouldn't be in 'git'. + + deleted: compile + deleted: config.guess + deleted: config.sub + deleted: depcomp + deleted: install-sh + deleted: ltmain.sh + deleted: missing + +commit 82b53188aaffad0e237461f8f1274794166feb3a +Author: Neil Brown +Date: Fri Jun 16 13:09:26 2006 +1000 + + Add support to auto-generate nfsmount* files for new nfs.mount program + +commit 4e2bae795e5eaf9922f0b966ab5df64994c836a2 +Author: Amit Gud +Date: Mon Jun 12 19:08:27 2006 -0400 + + Move NFS mount code from util-linux to nfs-utils - part 2 + + Adds the support functions needed for mount and umount. This + functionality will someday be available in the form of shared mount + library. + + Signed-off-by: Amit Gud + Signed-off-by: Steve Dickson + +commit a0520fa1a41bd33815b331b660b4545f2723495c +Author: Amit Gud +Date: Mon Jun 12 19:06:36 2006 -0400 + + Move NFS mount code from util-linux to nfs-utils - part 1 + + Adds the mount directory and the code to mount and umount the NFS file system. + + Signed-off-by: Amit Gud + Signed-off-by: Steve Dickson + 2006-06-05 NeilBrown - Remove debian/ at request of Debian maintainer "Steinar H. Gunderson" - fix_exportfs_with_multiple_matches.diff: Fixes a problem with exportfs -o diff --git a/configure.in b/configure.in index 8459ef8..6f9ab40 100644 --- a/configure.in +++ b/configure.in @@ -1,6 +1,6 @@ dnl Process this file with autoconf to produce a configure script. dnl -AC_INIT([linux nfs-utils],[1.0.8],[nfs@lists.sf.net],[nfs-utils]) +AC_INIT([linux nfs-utils],[1.0.9-pre1],[nfs@lists.sf.net],[nfs-utils]) AC_CANONICAL_BUILD([]) AC_CANONICAL_HOST([]) AC_CONFIG_SRCDIR(tools/getiversion/getiversion.c) @@ -107,12 +107,12 @@ AC_ARG_ENABLE(rquotad, fi AM_CONDITIONAL(CONFIG_RQUOTAD, [test "$enable_rquotad" = "yes"]) -AC_ARG_WITH(mount, - [AC_HELP_STRING([--without-mount], - [Create mount.nfs and do not use the util-linux mount(8) functionality. By default it doesn't.])], - use_mount=$withval, - use_mount=yes) - AM_CONDITIONAL(CONFIG_NOMOUNT, [test "$use_mount" = "no"]) +AC_ARG_ENABLE(mount, + [AC_HELP_STRING([--enable-mount], + [Create mount.nfs and don't use the util-linux mount(8) functionality. @<:@default=yes@:>@])], + enable_mount=$enableval, + enable_mount=yes) + AM_CONDITIONAL(CONFIG_MOUNT, [test "$enable_mount" = "yes"]) # Check whether user wants TCP wrappers support AC_TCP_WRAPPERS diff --git a/support/include/conn.h b/support/include/conn.h index ae19a3e..1761dc4 100644 --- a/support/include/conn.h +++ b/support/include/conn.h @@ -31,7 +31,8 @@ typedef struct { static const struct timeval TIMEOUT = { 20, 0 }; static const struct timeval RETRY_TIMEOUT = { 3, 0 }; -int clnt_ping(struct sockaddr_in *, const u_long, const u_long, const u_int); +int clnt_ping(struct sockaddr_in *, const u_long, const u_long, const u_int, + struct sockaddr_in *); u_long nfsvers_to_mnt(const u_long); u_long mntvers_to_nfs(const u_long); int get_socket(struct sockaddr_in *, u_int, int); diff --git a/support/include/nfs/nfs.h b/support/include/nfs/nfs.h index c7fc42c..f0286b2 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,15 @@ struct nfs_fh_old { #define NFSCTL_LOCKD 0x10000 #define LOCKDCTL_SVC NFSCTL_LOCKD +#define NFSCTL_VERUNSET(_cltbits, _v) ((_cltbits) &= ~(1 << ((_v) - 1))) +#define NFSCTL_UDPUNSET(_cltbits) ((_cltbits) &= ~(1 << (17 - 1))) +#define NFSCTL_TCPUNSET(_cltbits) ((_cltbits) &= ~(1 << (18 - 1))) + +#define NFSCTL_VERISSET(_cltbits, _v) ((_cltbits) & (1 << ((_v) - 1))) +#define NFSCTL_UDPISSET(_cltbits) ((_cltbits) & (1 << (17 - 1))) +#define NFSCTL_TCPISSET(_cltbits) ((_cltbits) & (1 << (18 - 1))) +#define NFSCTL_ALLBITS (~0) /* SVC */ struct nfsctl_svc { diff --git a/support/include/nfslib.h b/support/include/nfslib.h index 8c83262..3e25761 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, unsigned int portbits, char *haddr); int nfsaddclient(struct nfsctl_client *clp); int nfsdelclient(struct nfsctl_client *clp); int nfsexport(struct nfsctl_export *exp); diff --git a/support/misc/mountpoint.c b/support/misc/mountpoint.c index 6d0f34e..750b6e8 100644 --- a/support/misc/mountpoint.c +++ b/support/misc/mountpoint.c @@ -20,15 +20,20 @@ is_mountpoint(char *path) */ char *dotdot; struct stat stb, pstb; + int rv; + + dotdot = xmalloc(strlen(path)+4); - dotdot = malloc(strlen(path)+4); strcat(strcpy(dotdot, path), "/.."); if (lstat(path, &stb) != 0 || lstat(dotdot, &pstb) != 0) - return 0; - - if (stb.st_dev != pstb.st_dev - || stb.st_ino == pstb.st_ino) - return 1; - return 0; + rv = 0; + else + if (stb.st_dev != pstb.st_dev || + stb.st_ino == pstb.st_ino) + rv = 1; + else + rv = 0; + free(dotdot); + return rv; } diff --git a/support/nfs/cacheio.c b/support/nfs/cacheio.c index d7ad429..3e868d8 100644 --- a/support/nfs/cacheio.c +++ b/support/nfs/cacheio.c @@ -259,9 +259,9 @@ cache_flush(int force) "nfsd.export", NULL }; - stb.st_mtime = time(0); - if (!force) - stat(_PATH_ETAB, &stb); + if (force || + stat(_PATH_ETAB, &stb) != 0) + stb.st_mtime = time(0); sprintf(stime, "%ld\n", stb.st_mtime); for (c=0; cachelist[c]; c++) { diff --git a/support/nfs/conn.c b/support/nfs/conn.c index bf2afad..733bf24 100644 --- a/support/nfs/conn.c +++ b/support/nfs/conn.c @@ -93,7 +93,7 @@ int get_socket(struct sockaddr_in *saddr, u_int p_prot, int resvp) return RPC_ANYSOCK; } } - if (type == SOCK_STREAM) { + if (type == SOCK_STREAM || type == SOCK_DGRAM) { cc = connect(so, (struct sockaddr *)saddr, namelen); if (cc < 0) { rpc_createerr.cf_stat = RPC_SYSTEMERROR; @@ -119,7 +119,7 @@ int get_socket(struct sockaddr_in *saddr, u_int p_prot, int resvp) */ int clnt_ping(struct sockaddr_in *saddr, const u_long prog, const u_long vers, - const u_int prot) + const u_int prot, struct sockaddr_in *caddr) { CLIENT *clnt=NULL; int sock, stat; @@ -161,8 +161,15 @@ clnt_ping(struct sockaddr_in *saddr, const u_long prog, const u_long vers, rpc_createerr.cf_stat = stat; } clnt_destroy(clnt); - if (sock != -1) + if (sock != -1) { + if (caddr) { + /* Get the address of our end of this connection */ + int len = sizeof(*caddr); + if (getsockname(sock, caddr, &len) != 0) + caddr->sin_family = 0; + } close(sock); + } if (stat == RPC_SUCCESS) return 1; diff --git a/support/nfs/nfssvc.c b/support/nfs/nfssvc.c index 38240a0..a6ea410 100644 --- a/support/nfs/nfssvc.c +++ b/support/nfs/nfssvc.c @@ -10,18 +10,136 @@ #include #endif +#include +#include +#include #include #include +#include +#include + #include "nfslib.h" +#define NFSD_PORTS_FILE "/proc/fs/nfsd/portlist" +#define NFSD_VERS_FILE "/proc/fs/nfsd/versions" +#define NFSD_THREAD_FILE "/proc/fs/nfsd/threads" + +static void +nfssvc_setfds(int port, unsigned int ctlbits, char *haddr) +{ + int fd, on=1; + char buf[BUFSIZ]; + int udpfd = -1, tcpfd = -1; + struct sockaddr_in sin; + + fd = open(NFSD_PORTS_FILE, O_WRONLY); + if (fd < 0) + return; + sin.sin_family = AF_INET; + sin.sin_port = htons(port); + sin.sin_addr.s_addr = inet_addr(haddr); + + if (NFSCTL_UDPISSET(ctlbits)) { + udpfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (udpfd < 0) { + syslog(LOG_ERR, "nfssvc: unable to create UPD socket: " + "errno %d (%s)\n", errno, strerror(errno)); + exit(1); + } + if (bind(udpfd, (struct sockaddr *)&sin, sizeof(sin)) < 0){ + syslog(LOG_ERR, "nfssvc: unable to bind UPD socket: " + "errno %d (%s)\n", errno, strerror(errno)); + exit(1); + } + } + + if (NFSCTL_TCPISSET(ctlbits)) { + tcpfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (tcpfd < 0) { + syslog(LOG_ERR, "nfssvc: unable to createt tcp socket: " + "errno %d (%s)\n", errno, strerror(errno)); + exit(1); + } + if (setsockopt(tcpfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) { + syslog(LOG_ERR, "nfssvc: unable to set SO_REUSEADDR: " + "errno %d (%s)\n", errno, strerror(errno)); + exit(1); + } + if (bind(tcpfd, (struct sockaddr *)&sin, sizeof(sin)) < 0){ + syslog(LOG_ERR, "nfssvc: unable to bind TCP socket: " + "errno %d (%s)\n", errno, strerror(errno)); + exit(1); + } + if (listen(tcpfd, 64) < 0){ + syslog(LOG_ERR, "nfssvc: unable to create listening socket: " + "errno %d (%s)\n", errno, strerror(errno)); + exit(1); + } + } + if (udpfd >= 0) { + snprintf(buf, BUFSIZ,"%d\n", udpfd); + if (write(fd, buf, strlen(buf)) != strlen(buf)) { + syslog(LOG_ERR, + "nfssvc: writting fds to kernel failed: errno %d (%s)", + errno, strerror(errno)); + } + close(fd); + fd = -1; + } + if (tcpfd >= 0) { + if (fd < 0) + fd = open(NFSD_PORTS_FILE, O_WRONLY); + snprintf(buf, BUFSIZ,"%d\n", tcpfd); + if (write(fd, buf, strlen(buf)) != strlen(buf)) { + syslog(LOG_ERR, + "nfssvc: writting fds to kernel failed: errno %d (%s)", + errno, strerror(errno)); + } + } + close(fd); + + return; +} +static void +nfssvc_versbits(unsigned int ctlbits) +{ + int fd, n, off; + char buf[BUFSIZ], *ptr; + + ptr = buf; + off = 0; + fd = open(NFSD_VERS_FILE, 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, unsigned protobits, + char *haddr) { struct nfsctl_arg arg; int fd; - fd = open("/proc/fs/nfsd/threads", O_WRONLY); + nfssvc_setfds(port, protobits, haddr); + + nfssvc_versbits(versbits); + + fd = open(NFSD_THREAD_FILE, O_WRONLY); if (fd < 0) fd = open("/proc/fs/nfs/threads", O_WRONLY); if (fd >= 0) { diff --git a/support/nfs/svc_socket.c b/support/nfs/svc_socket.c index 888c915..c41a1a3 100644 --- a/support/nfs/svc_socket.c +++ b/support/nfs/svc_socket.c @@ -42,7 +42,7 @@ svc_socket (u_long number, int type, int protocol, int reuse) socklen_t len = sizeof (struct sockaddr_in); char rpcdata [1024], servdata [1024]; struct rpcent rpcbuf, *rpcp; - struct servent servbuf, *servp; + struct servent servbuf, *servp = NULL; int sock, ret; const char *proto = protocol == IPPROTO_TCP ? "tcp" : "udp"; diff --git a/support/nfs/xio.c b/support/nfs/xio.c index 1ce5157..221cce6 100644 --- a/support/nfs/xio.c +++ b/support/nfs/xio.c @@ -95,11 +95,6 @@ xgettok(XFILE *xfp, char sepa, char *tok, int len) while (i < len && (c = xgetc(xfp)) != EOF && (quoted || (c != sepa && !isspace(c)))) { - if (!quoted && i == 0 && c == '#') { - c = xskipcomment(xfp); - xfp->x_line++; - break; - } if (c == '"') { quoted = !quoted; continue; @@ -164,7 +159,12 @@ xskip(XFILE *xfp, char *str) { int c; - while ((c = xgetc(xfp)) != EOF && strchr(str, c)); + while ((c = xgetc(xfp)) != EOF) { + if (c == '#') + c = xskipcomment(xfp); + if (strchr(str, c) == NULL) + break; + } xungetc(c, xfp); } diff --git a/tools/rpcgen/rpc_parse.c b/tools/rpcgen/rpc_parse.c index 2a2b7e0..52300a4 100644 --- a/tools/rpcgen/rpc_parse.c +++ b/tools/rpcgen/rpc_parse.c @@ -94,6 +94,7 @@ get_definition(void) def_const(defp); break; case TOK_EOF: + free(defp); return (NULL); default: error("definition keyword expected"); @@ -290,7 +291,6 @@ def_union(definition *defp) declaration dec; case_list *cases; case_list **tailp; - int flag; defp->def_kind = DEF_UNION; scan(TOK_IDENT, &tok); @@ -309,7 +309,6 @@ def_union(definition *defp) cases->case_name = tok.str; scan(TOK_COLON, &tok); /* now peek at next token */ - flag=0; if(peekscan(TOK_CASE,&tok)) { @@ -325,14 +324,6 @@ def_union(definition *defp) }while(peekscan(TOK_CASE,&tok)); } - else - if(flag) - { - - *tailp = cases; - tailp = &cases->next; - cases = ALLOC(case_list); - }; get_declaration(&dec, DEF_UNION); cases->case_decl = dec; diff --git a/tools/rpcgen/rpc_scan.c b/tools/rpcgen/rpc_scan.c index c0ddc14..a6f442c 100644 --- a/tools/rpcgen/rpc_scan.c +++ b/tools/rpcgen/rpc_scan.c @@ -468,6 +468,7 @@ docppline(char *line, int *lineno, char **fname) *p = 0; if (*file == 0) { *fname = NULL; + free(file); } else { *fname = file; } diff --git a/utils/Makefile.am b/utils/Makefile.am index 259bec3..9cdb4ea 100644 --- a/utils/Makefile.am +++ b/utils/Makefile.am @@ -14,7 +14,7 @@ if CONFIG_GSS OPTDIRS += gssd endif -if CONFIG_NOMOUNT +if CONFIG_MOUNT OPTDIRS += mount endif diff --git a/utils/idmapd/cfg.c b/utils/idmapd/cfg.c index b22a7c9..16d392a 100644 --- a/utils/idmapd/cfg.c +++ b/utils/idmapd/cfg.c @@ -487,8 +487,10 @@ conf_get_list (char *section, char *tag) if (!node) goto cleanup; node->field = strdup (field); - if (!node->field) + if (!node->field) { + free(node); goto cleanup; + } TAILQ_INSERT_TAIL (&list->fields, node, link); } free (liststr); @@ -523,8 +525,10 @@ conf_get_tag_list (char *section) if (!node) goto cleanup; node->field = strdup (cb->tag); - if (!node->field) + if (!node->field) { + free(node); goto cleanup; + } TAILQ_INSERT_TAIL (&list->fields, node, link); } return list; @@ -708,7 +712,7 @@ conf_remove (int transaction, char *section, char *tag) return 0; fail: - if (node->section) + if (node && node->section) free (node->section); if (node) free (node); diff --git a/utils/idmapd/idmapd.c b/utils/idmapd/idmapd.c index 16b1316..21a1916 100644 --- a/utils/idmapd/idmapd.c +++ b/utils/idmapd/idmapd.c @@ -1006,10 +1006,15 @@ mydaemon(int nochdir, int noclose) if (noclose == 0) { tempfd = open("/dev/null", O_RDWR); - dup2(tempfd, 0); - dup2(tempfd, 1); - dup2(tempfd, 2); - closeall(3); + if (tempfd < 0) + tempfd = open("/", O_RDONLY); + if (tempfd >= 0) { + dup2(tempfd, 0); + dup2(tempfd, 1); + dup2(tempfd, 2); + closeall(3); + } else + closeall(0); } return; diff --git a/utils/mount/Makefile.am b/utils/mount/Makefile.am index 3ed0ace..4a2f437 100644 --- a/utils/mount/Makefile.am +++ b/utils/mount/Makefile.am @@ -2,48 +2,16 @@ man8_MANS = mount.nfs.man umount.nfs.man -RPCGEN = $(top_builddir)/tools/rpcgen/rpcgen - -GENFILES_CLNT = nfsmount_clnt.c -GENFILES_XDR = nfsmount_xdr.c -GENFILES_H = nfsmount.h - -GENFILES = $(GENFILES_CLNT) $(GENFILES_XDR) $(GENFILES_H) - sbin_PROGRAMS = mount.nfs EXTRA_DIST = nfsmount.x $(man8_MANS) mount_nfs_SOURCES = mount.c nfsmount.c nfs4mount.c nfsumount.c \ - nfsmount_xdr.c mount_constants.h nfs4_mount.h nfsmount.h \ - nfs_mount4.h - -BUILT_SOURCES = $(GENFILES) -mount_nfs_LDADD = ../../support/nfs/libnfs.a - - -$(RPCGEN): - make -C ../../tools/rpcgen all - -$(GENFILES_CLNT): %_clnt.c: %.x $(RPCGEN) - test -f $@ && rm -rf $@ || true - $(RPCGEN) -l -o $@ $< - -$(GENFILES_SVC): %_svc.c: %.x $(RPCGEN) - test -f $@ && rm -rf $@ || true - $(RPCGEN) -m -o $@ $< - -$(GENFILES_XDR): %_xdr.c: %.x $(RPCGEN) - test -f $@ && rm -rf $@ || true - $(RPCGEN) -c -o $@ $< - -$(GENFILES_H): %.h: %.x $(RPCGEN) - test -f $@ && rm -rf $@ || true - $(RPCGEN) -h -o $@ $< + mount_constants.h nfs4_mount.h nfs_mount4.h +mount_nfs_LDADD = ../../support/nfs/libnfs.a \ + ../../support/export/libexport.a MAINTAINERCLEANFILES = Makefile.in -CLEANFILES = $(GENFILES) - install-exec-hook: (cd $(DESTDIR)$(sbindir) && \ ln -sf $(sbin_PROGRAMS) mount.nfs4 && \ diff --git a/utils/mount/mount.c b/utils/mount/mount.c index 270a179..ca87e3d 100644 --- a/utils/mount/mount.c +++ b/utils/mount/mount.c @@ -37,7 +37,7 @@ #include "nfs_mount.h" #include "nfs4_mount.h" #include "nfsumount.h" -#include "nfsmount.h" +#include "mount.h" char *progname; int nomtab; diff --git a/utils/mount/nfs4mount.c b/utils/mount/nfs4mount.c index b59c27c..717ad56 100644 --- a/utils/mount/nfs4mount.c +++ b/utils/mount/nfs4mount.c @@ -189,9 +189,10 @@ int nfs4mount(const char *spec, const char *node, int *flags, static struct nfs4_mount_data data; static char hostdir[1024]; static char ip_addr[16] = "127.0.0.1"; - static struct sockaddr_in server_addr; + static struct sockaddr_in server_addr, client_addr; static int pseudoflavour[MAX_USER_FLAVOUR]; int num_flavour = 0; + int ip_addr_in_opts = 0; char *hostname, *dirname, *old_opts; char new_opts[1024]; @@ -302,6 +303,7 @@ int nfs4mount(const char *spec, const char *node, int *flags, opteq+1); strncpy(ip_addr,opteq+1, sizeof(ip_addr)); ip_addr[sizeof(ip_addr)-1] = '\0'; + ip_addr_in_opts = 1; } else if (!strcmp(opt, "sec")) { num_flavour = parse_sec(opteq+1, pseudoflavour); if (!num_flavour) @@ -412,9 +414,19 @@ int nfs4mount(const char *spec, const char *node, int *flags, NFS_PROGRAM, 4, data.proto == IPPROTO_UDP ? "udp" : "tcp", ntohs(server_addr.sin_port)); } - clnt_ping(&server_addr, NFS_PROGRAM, 4, data.proto); - if (rpc_createerr.cf_stat == RPC_SUCCESS) + client_addr.sin_family = 0; + client_addr.sin_addr.s_addr = 0; + clnt_ping(&server_addr, NFS_PROGRAM, 4, data.proto, &client_addr); + if (rpc_createerr.cf_stat == RPC_SUCCESS) { + if (!ip_addr_in_opts && + client_addr.sin_family != 0 && + client_addr.sin_addr.s_addr != 0) { + snprintf(ip_addr, sizeof(ip_addr), "%s", + inet_ntoa(client_addr.sin_addr)); + data.client_addr.len = strlen(ip_addr); + } break; + } switch(rpc_createerr.cf_stat){ case RPC_TIMEDOUT: diff --git a/utils/mount/nfsmount.c b/utils/mount/nfsmount.c index 1266660..507ccdb 100644 --- a/utils/mount/nfsmount.c +++ b/utils/mount/nfsmount.c @@ -59,7 +59,7 @@ #include "conn.h" #include "xcommon.h" -#include "nfsmount.h" +#include "mount.h" #include "nfsumount.h" #include "nfs_mount.h" #include "mount_constants.h" @@ -376,7 +376,7 @@ probe_port(clnt_addr_t *server, inet_ntoa(saddr->sin_addr), prog, *p_vers, *p_prot == IPPROTO_UDP ? "udp" : "tcp", p_port); } - if (clnt_ping(saddr, prog, *p_vers, *p_prot)) + if (clnt_ping(saddr, prog, *p_vers, *p_prot, NULL)) goto out_ok; if (rpc_createerr.cf_stat == RPC_TIMEDOUT) goto out_bad; @@ -1084,11 +1084,11 @@ nfsmount(const char *spec, const char *node, int *flags, } #if NFS_MOUNT_VERSION >= 5 mountres = &mntres.nfsv3.mountres3_u.mountinfo; - i = mountres->auth_flavours.auth_flavours_len; + i = mountres->auth_flavors.auth_flavors_len; if (i <= 0) - goto noauth_flavours; + goto noauth_flavors; - flavor = mountres->auth_flavours.auth_flavours_val; + flavor = mountres->auth_flavors.auth_flavors_val; while (--i >= 0) { if (flavor[i] == data.pseudoflavor) yum = 1; @@ -1106,7 +1106,7 @@ nfsmount(const char *spec, const char *node, int *flags, nfs_call_umount(&mnt_server, &dirname); goto fail; } -noauth_flavours: +noauth_flavors: #endif fhandle = &mntres.nfsv3.mountres3_u.mountinfo.fhandle; memset(data.old_root.data, 0, NFS_FHSIZE); diff --git a/utils/mount/nfsmount.x b/utils/mount/nfsmount.x deleted file mode 100644 index ad4bf99..0000000 --- a/utils/mount/nfsmount.x +++ /dev/null @@ -1,336 +0,0 @@ -%/* -% * Sun RPC is a product of Sun Microsystems, Inc. and is provided for -% * unrestricted use provided that this legend is included on all tape -% * media and as a part of the software program in whole or part. Users -% * may copy or modify Sun RPC without charge, but are not authorized -% * to license or distribute it to anyone else except as part of a product or -% * program developed by the user or with the express written consent of -% * Sun Microsystems, Inc. -% * -% * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE -% * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR -% * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. -% * -% * Sun RPC is provided with no support and without any obligation on the -% * part of Sun Microsystems, Inc. to assist in its use, correction, -% * modification or enhancement. -% * -% * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE -% * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC -% * OR ANY PART THEREOF. -% * -% * In no event will Sun Microsystems, Inc. be liable for any lost revenue -% * or profits or other special, indirect and consequential damages, even if -% * Sun has been advised of the possibility of such damages. -% * -% * Sun Microsystems, Inc. -% * 2550 Garcia Avenue -% * Mountain View, California 94043 -% */ - -%/* -% * Copyright (c) 1985, 1990 by Sun Microsystems, Inc. -% */ -% -%/* from @(#)mount.x 1.3 91/03/11 TIRPC 1.0 */ - -/* - * Protocol description for the mount program - */ - -#ifdef RPC_HDR -%#ifndef _rpcsvc_mount_h -%#define _rpcsvc_mount_h -#endif - -#ifdef RPC_CLNT -%#include /* for memset() */ -#endif -%#include - -const MNTPATHLEN = 1024; /* maximum bytes in a pathname argument */ -const MNTNAMLEN = 255; /* maximum bytes in a name argument */ -const FHSIZE = 32; /* size in bytes of a file handle */ -const FHSIZE3 = 64; /* size in bytes of a file handle */ - -/* - * The fhandle is the file handle that the server passes to the client. - * All file operations are done using the file handles to refer to a file - * or a directory. The file handle can contain whatever information the - * server needs to distinguish an individual file. - */ -typedef opaque fhandle[FHSIZE]; -typedef opaque fhandle3; - -enum mountstat3 { - MNT_OK = 0, /* no error */ - MNT3ERR_PERM = 1, /* not owner */ - MNT3ERR_NOENT = 2, /* No such file or directory */ - MNT3ERR_IO = 5, /* I/O error */ - MNT3ERR_ACCES = 13, /* Permission denied */ - MNT3ERR_NOTDIR = 20, /* Not a directory */ - MNT3ERR_INVAL = 22, /* Invalid argument */ - MNT3ERR_NAMETOOLONG = 63, /* File name too long */ - MNT3ERR_NOTSUPP = 10004, /* Operation not supported */ - MNT3ERR_SERVERFAULT = 10006 /* A failure on the server */ -}; - -/* - * If a status of zero is returned, the call completed successfully, and - * a file handle for the directory follows. A non-zero status indicates - * some sort of error. The status corresponds with UNIX error numbers. - */ -union fhstatus switch (unsigned fhs_status) { -case 0: - fhandle fhs_fhandle; -default: - void; -}; - -struct mountres3_ok { - fhandle3 fhandle; - int auth_flavours<>; -}; - -union mountres3 switch (mountstat3 fhs_status) { -case MNT_OK: - mountres3_ok mountinfo; -default: - void; -}; - -/* - * The type dirpath is the pathname of a directory - */ -typedef string dirpath; - -/* - * The type name is used for arbitrary names (hostnames, groupnames) - */ -typedef string name; - -/* - * A list of who has what mounted - */ -typedef struct mountbody *mountlist; -struct mountbody { - name ml_hostname; - dirpath ml_directory; - mountlist ml_next; -}; - -/* - * A list of netgroups - */ -typedef struct groupnode *groups; -struct groupnode { - name gr_name; - groups gr_next; -}; - -/* - * A list of what is exported and to whom - */ -typedef struct exportnode *exports; -struct exportnode { - dirpath ex_dir; - groups ex_groups; - exports ex_next; -}; - -/* - * POSIX pathconf information - */ -struct ppathcnf { - int pc_link_max; /* max links allowed */ - short pc_max_canon; /* max line len for a tty */ - short pc_max_input; /* input a tty can eat all at once */ - short pc_name_max; /* max file name length (dir entry) */ - short pc_path_max; /* max path name length (/x/y/x/.. ) */ - short pc_pipe_buf; /* size of a pipe (bytes) */ - u_char pc_vdisable; /* safe char to turn off c_cc[i] */ - char pc_xxx; /* alignment padding; cc_t == char */ - short pc_mask[2]; /* validity and boolean bits */ -}; - -program MOUNTPROG { - /* - * Version one of the mount protocol communicates with version two - * of the NFS protocol. The only connecting point is the fhandle - * structure, which is the same for both protocols. - */ - version MOUNTVERS { - /* - * Does no work. It is made available in all RPC services - * to allow server reponse testing and timing - */ - void - MOUNTPROC_NULL(void) = 0; - - /* - * If fhs_status is 0, then fhs_fhandle contains the - * file handle for the directory. This file handle may - * be used in the NFS protocol. This procedure also adds - * a new entry to the mount list for this client mounting - * the directory. - * Unix authentication required. - */ - fhstatus - MOUNTPROC_MNT(dirpath) = 1; - - /* - * Returns the list of remotely mounted filesystems. The - * mountlist contains one entry for each hostname and - * directory pair. - */ - mountlist - MOUNTPROC_DUMP(void) = 2; - - /* - * Removes the mount list entry for the directory - * Unix authentication required. - */ - void - MOUNTPROC_UMNT(dirpath) = 3; - - /* - * Removes all of the mount list entries for this client - * Unix authentication required. - */ - void - MOUNTPROC_UMNTALL(void) = 4; - - /* - * Returns a list of all the exported filesystems, and which - * machines are allowed to import it. - */ - exports - MOUNTPROC_EXPORT(void) = 5; - - /* - * Identical to MOUNTPROC_EXPORT above - */ - exports - MOUNTPROC_EXPORTALL(void) = 6; - } = 1; - - /* - * Version two of the mount protocol communicates with version two - * of the NFS protocol. - * The only difference from version one is the addition of a POSIX - * pathconf call. - */ - version MOUNTVERS_POSIX { - /* - * Does no work. It is made available in all RPC services - * to allow server reponse testing and timing - */ - void - MOUNTPROC_NULL(void) = 0; - - /* - * If fhs_status is 0, then fhs_fhandle contains the - * file handle for the directory. This file handle may - * be used in the NFS protocol. This procedure also adds - * a new entry to the mount list for this client mounting - * the directory. - * Unix authentication required. - */ - fhstatus - MOUNTPROC_MNT(dirpath) = 1; - - /* - * Returns the list of remotely mounted filesystems. The - * mountlist contains one entry for each hostname and - * directory pair. - */ - mountlist - MOUNTPROC_DUMP(void) = 2; - - /* - * Removes the mount list entry for the directory - * Unix authentication required. - */ - void - MOUNTPROC_UMNT(dirpath) = 3; - - /* - * Removes all of the mount list entries for this client - * Unix authentication required. - */ - void - MOUNTPROC_UMNTALL(void) = 4; - - /* - * Returns a list of all the exported filesystems, and which - * machines are allowed to import it. - */ - exports - MOUNTPROC_EXPORT(void) = 5; - - /* - * Identical to MOUNTPROC_EXPORT above - */ - exports - MOUNTPROC_EXPORTALL(void) = 6; - - /* - * POSIX pathconf info (Sun hack) - */ - ppathcnf - MOUNTPROC_PATHCONF(dirpath) = 7; - } = 2; - version MOUNT_V3 { - /* - * Does no work. It is made available in all RPC services - * to allow server reponse testing and timing - */ - void - MOUNTPROC3_NULL(void) = 0; - - /* - * If fhs_status is 0, then fhs_fhandle contains the - * file handle for the directory. This file handle may - * be used in the NFS protocol. This procedure also adds - * a new entry to the mount list for this client mounting - * the directory. - * Unix authentication required. - */ - mountres3 - MOUNTPROC3_MNT(dirpath) = 1; - - /* - * Returns the list of remotely mounted filesystems. The - * mountlist contains one entry for each hostname and - * directory pair. - */ - mountlist - MOUNTPROC3_DUMP(void) = 2; - - /* - * Removes the mount list entry for the directory - * Unix authentication required. - */ - void - MOUNTPROC3_UMNT(dirpath) = 3; - - /* - * Removes all of the mount list entries for this client - * Unix authentication required. - */ - void - MOUNTPROC3_UMNTALL(void) = 4; - - /* - * Returns a list of all the exported filesystems, and which - * machines are allowed to import it. - */ - exports - MOUNTPROC3_EXPORT(void) = 5; - - } = 3; -} = 100005; - -#ifdef RPC_HDR -%#endif /*!_rpcsvc_mount_h*/ -#endif diff --git a/utils/mount/nfsumount.c b/utils/mount/nfsumount.c index d1d476a..28f4244 100644 --- a/utils/mount/nfsumount.c +++ b/utils/mount/nfsumount.c @@ -30,7 +30,7 @@ #include "conn.h" #include "mount_constants.h" -#include "nfsmount.h" +#include "mount.h" #include "nfsumount.h" #if !defined(MNT_FORCE) diff --git a/utils/mount/nfsumount.h b/utils/mount/nfsumount.h index c089275..e37eaff 100644 --- a/utils/mount/nfsumount.h +++ b/utils/mount/nfsumount.h @@ -2,7 +2,7 @@ #define _NFS_UMOUNT_H #include "conn.h" -#include "nfsmount.h" +#include "mount.h" int nfsumount(int, char **); int nfs_call_umount(clnt_addr_t *, dirpath *); diff --git a/utils/nfsd/nfsd.c b/utils/nfsd/nfsd.c index 05506ee..d0bbfb3 100644 --- a/utils/nfsd/nfsd.c +++ b/utils/nfsd/nfsd.c @@ -20,15 +20,35 @@ #include #include #include +#include +#include +#include + #include "nfslib.h" static void usage(const char *); +static struct option longopts[] = +{ + { "host", 1, 0, 'H' }, + { "help", 0, 0, 'h' }, + { "no-nfs-version", 1, 0, 'N' }, + { "no-tcp", 0, 0, 'T' }, + { "no-udp", 0, 0, 'U' }, + { "port", 1, 0, 'P' }, + { "port", 1, 0, 'p' }, + { NULL, 0, 0, 0 } +}; +unsigned int protobits = NFSCTL_ALLBITS; +unsigned int versbits = NFSCTL_ALLBITS; +char *haddr = NULL; + 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; + struct hostent *hp; ent = getservbyname ("nfs", "udp"); if (ent != NULL) @@ -36,8 +56,19 @@ main(int argc, char **argv) else port = 2049; - while ((c = getopt(argc, argv, "hp:P:")) != EOF) { + while ((c = getopt_long(argc, argv, "H:hN:p:P:TU", longopts, NULL)) != EOF) { switch(c) { + case 'H': + if (inet_addr(optarg) != INADDR_NONE) { + haddr = strdup(optarg); + } else if ((hp = gethostbyname(optarg)) != NULL) { + haddr = inet_ntoa((*(struct in_addr*)(hp->h_addr_list[0]))); + } else { + fprintf(stderr, "%s: Unknown hostname: %s\n", + argv[0], optarg); + usage(argv [0]); + } + break; case 'P': /* XXX for nfs-server compatibility */ case 'p': port = atoi(optarg); @@ -47,12 +78,54 @@ 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': + case 'T': + NFSCTL_TCPUNSET(protobits); + break; + case 'U': + NFSCTL_UDPUNSET(protobits); + break; default: + fprintf(stderr, "Invalid argument: '%c'\n", c); + case 'h': usage(argv[0]); } } + /* + * Do some sanity checking, if the ctlbits are set + */ + if (!NFSCTL_UDPISSET(protobits) && !NFSCTL_TCPISSET(protobits)) { + fprintf(stderr, "invalid protocol specified\n"); + exit(1); + } + 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 (NFSCTL_VERISSET(versbits, 4) && !NFSCTL_TCPISSET(versbits)) { + fprintf(stderr, "version 4 requires the TCP protocol\n"); + exit(1); + } + if (haddr == NULL) { + struct in_addr in = {INADDR_ANY}; + haddr = strdup(inet_ntoa(in)); + } if (chdir(NFS_STATEDIR)) { fprintf(stderr, "%s: chdir(%s) failed: %s\n", @@ -69,7 +142,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 +156,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, protobits, haddr)) < 0) { int e = errno; - openlog("nfsd", LOG_PID, LOG_DAEMON); syslog(LOG_ERR, "nfssvc: %s", strerror(e)); closelog(); } @@ -97,7 +169,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 [-H hostname] [-p|-P|--port port] [-N|--no-nfs-version version ] [-T|--no-tcp] [-U|--no-udp] nrservs\n", + prog); exit(2); } diff --git a/utils/nfsd/nfsd.man b/utils/nfsd/nfsd.man index a890ea6..4ac709c 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,39 @@ server provides an ancillary service needed to satisfy mount requests by NFS clients. .SH OPTIONS .TP -.BI \-p " port" +.B \-H " or " \-\-host hostname +specify a particular hostname (or address) that NFS requests will +be accepted on. By default, +.B rpc.nfsd +will accept NFS requests on all known network addresses. +Note that +.B lockd +(which performs file locking services for NFS) may still accept +request on all known network addresses. This may change in future +releases of the Linux Kernel. +.TP +.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 +.B \-T " or " \-\-no-tcp +Disable +.B rpc.nfsd +from accepting TCP connections from clients. +.TP +.B \-U " or " \-\-no-udp +Disable +.B rpc.nfsd +from accepting UDP connections from clients. +.TP .I nproc specify the number of NFS server threads. By default, just one thread is started. However, for optimum performance several threads diff --git a/utils/rquotad/rquota_server.c b/utils/rquotad/rquota_server.c index 109c94e..e3715bd 100644 --- a/utils/rquotad/rquota_server.c +++ b/utils/rquotad/rquota_server.c @@ -201,7 +201,6 @@ getquota_rslt *getquotainfo(int flags, caddr_t *argp, struct svc_req *rqstp) free(qfpathname); continue; } - free(qfpathname); lseek(fd, (long) dqoff(id), L_SET); switch (read(fd, &dq_dqb, sizeof(struct dqblk))) { case 0:/* EOF */ @@ -215,6 +214,7 @@ getquota_rslt *getquotainfo(int flags, caddr_t *argp, struct svc_req *rqstp) break; default: /* ERROR */ close(fd); + free(qfpathname); continue; } close(fd); @@ -228,6 +228,7 @@ getquota_rslt *getquotainfo(int flags, caddr_t *argp, struct svc_req *rqstp) dqb.dqb_btime = dq_dqb.dqb_btime; dqb.dqb_itime = dq_dqb.dqb_itime; } + free(qfpathname); endmntent(fp); if (err && (flags & ACTIVE)) { diff --git a/utils/statd/notlist.c b/utils/statd/notlist.c index 4f52b1d..b74d9df 100644 --- a/utils/statd/notlist.c +++ b/utils/statd/notlist.c @@ -54,15 +54,13 @@ nlist_new(char *my_name, char *mon_name, int state) { notify_list *new; - if (!(new = (notify_list *) xmalloc(sizeof(notify_list)))) - return NULL; + new = (notify_list *) xmalloc(sizeof(notify_list)); memset(new, 0, sizeof(*new)); NL_TIMES(new) = MAX_TRIES; NL_STATE(new) = state; - if (!(NL_MY_NAME(new) = xstrdup(my_name)) - || !(NL_MON_NAME(new) = xstrdup(mon_name))) - return NULL; + NL_MY_NAME(new) = xstrdup(my_name); + NL_MON_NAME(new) = xstrdup(mon_name); return new; }