+commit 49b164d978ee6266df7ba0bd335cb34337e7c381
+Author: Steve Dickson <SteveD@redhat.com>
+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 <SteveD@redhat.com>
+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 <neilb@suse.de>
+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 <neilb@suse.de>
+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 <neilb@suse.de>
+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 <agud@redhat.com>
+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 <agud@redhat.com>
+ Signed-off-by: Steve Dickson <steved@redhat.com>
+
+commit ceeffc1f76485b4084b2c61f4ff3c40e4f51c3b8
+Author: Amit Gud <gud@eth.net>
+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 <agud@redhat.com>
+ Signed-off-by: Steve Dickson <steved@redhat.com>
+
+commit c2db41e8abb6ddc9d03a0c91c6db043fa0f85a8f
+Author: Neil Brown <neilb@suse.de>
+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 <gnb@melbourne.sgi.com>
+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 <neilb@suse.de>
+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 <neilb@suse.de>
+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 <agud@redhat.com>
+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 <agud@redhat.com>
+ Signed-off-by: Steve Dickson <steved@redhat.com>
+
+commit a0520fa1a41bd33815b331b660b4545f2723495c
+Author: Amit Gud <agud@redhat.com>
+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 <agud@redhat.com>
+ Signed-off-by: Steve Dickson <steved@redhat.com>
+
2006-06-05 NeilBrown <neilb@suse.de>
- Remove debian/ at request of Debian maintainer "Steinar H. Gunderson" <sesse@debian.org>
- fix_exportfs_with_multiple_matches.diff: Fixes a problem with exportfs -o
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)
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
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);
#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];
#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 {
* 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);
*/
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;
}
"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++) {
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;
*/
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;
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;
#include <config.h>
#endif
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
+#include <errno.h>
+#include <syslog.h>
+
#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) {
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";
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;
{
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);
}
def_const(defp);
break;
case TOK_EOF:
+ free(defp);
return (NULL);
default:
error("definition keyword expected");
declaration dec;
case_list *cases;
case_list **tailp;
- int flag;
defp->def_kind = DEF_UNION;
scan(TOK_IDENT, &tok);
cases->case_name = tok.str;
scan(TOK_COLON, &tok);
/* now peek at next token */
- flag=0;
if(peekscan(TOK_CASE,&tok))
{
}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;
*p = 0;
if (*file == 0) {
*fname = NULL;
+ free(file);
} else {
*fname = file;
}
OPTDIRS += gssd
endif
-if CONFIG_NOMOUNT
+if CONFIG_MOUNT
OPTDIRS += mount
endif
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);
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;
return 0;
fail:
- if (node->section)
+ if (node && node->section)
free (node->section);
if (node)
free (node);
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;
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 && \
#include "nfs_mount.h"
#include "nfs4_mount.h"
#include "nfsumount.h"
-#include "nfsmount.h"
+#include "mount.h"
char *progname;
int nomtab;
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];
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)
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:
#include "conn.h"
#include "xcommon.h"
-#include "nfsmount.h"
+#include "mount.h"
#include "nfsumount.h"
#include "nfs_mount.h"
#include "mount_constants.h"
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;
}
#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;
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);
+++ /dev/null
-%/*
-% * 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 <string.h> /* for memset() */
-#endif
-%#include <asm/types.h>
-
-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<FHSIZE3>;
-
-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<MNTPATHLEN>;
-
-/*
- * The type name is used for arbitrary names (hostnames, groupnames)
- */
-typedef string name<MNTNAMLEN>;
-
-/*
- * 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
#include "conn.h"
#include "mount_constants.h"
-#include "nfsmount.h"
+#include "mount.h"
#include "nfsumount.h"
#if !defined(MNT_FORCE)
#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 *);
#include <getopt.h>
#include <syslog.h>
#include <netdb.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
#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)
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);
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",
count = 1;
}
}
-
/* KLUDGE ALERT:
Some kernels let nfsd kernel threads inherit open files
from the program that spawns them (i.e. us). So close
}
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();
}
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);
}
.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
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
free(qfpathname);
continue;
}
- free(qfpathname);
lseek(fd, (long) dqoff(id), L_SET);
switch (read(fd, &dq_dqb, sizeof(struct dqblk))) {
case 0:/* EOF */
break;
default: /* ERROR */
close(fd);
+ free(qfpathname);
continue;
}
close(fd);
dqb.dqb_btime = dq_dqb.dqb_btime;
dqb.dqb_itime = dq_dqb.dqb_itime;
}
+ free(qfpathname);
endmntent(fp);
if (err && (flags & ACTIVE)) {
{
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;
}