rpms/nfs-utils/devel nfs-utils-1.2.1-rc3.patch, NONE, 1.1 nfs-utils.spec, 1.238, 1.239 nfs-utils-1.2.0-nfsd-41vers.patch, 1.1, NONE

Steve Dickson steved at fedoraproject.org
Sun Aug 16 20:03:23 UTC 2009


Author: steved

Update of /cvs/pkgs/rpms/nfs-utils/devel
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv1640

Modified Files:
	nfs-utils.spec 
Added Files:
	nfs-utils-1.2.1-rc3.patch 
Removed Files:
	nfs-utils-1.2.0-nfsd-41vers.patch 
Log Message:
 - Added upstream 1.2.1-rc3 patch
   - Add IPv6 support to nfsd
   - Allow nfssvc_setfds to properly deal with AF_INET6
   - Convert nfssvc_setfds to use getaddrinfo
   - Move check for active knfsd to helper function
   - Declare a static common buffer for nfssvc.c routine
   - Convert rpc.nfsd to use xlog() and add --debug and --syslog options


nfs-utils-1.2.1-rc3.patch:
 b/support/include/nfs/nfs.h |   15 +-
 b/support/include/nfslib.h  |    1 
 b/support/nfs/Makefile.am   |    2 
 b/utils/nfsd/Makefile.am    |    6 
 b/utils/nfsd/nfsd.c         |  263 +++++++++++++++++++++++++++++-----------
 b/utils/nfsd/nfsd.man       |   25 +++
 b/utils/nfsd/nfssvc.c       |  289 ++++++++++++++++++++++++++++++++++++++++++++
 b/utils/nfsd/nfssvc.h       |   27 ++++
 support/nfs/nfssvc.c        |  187 ----------------------------
 9 files changed, 545 insertions(+), 270 deletions(-)

--- NEW FILE nfs-utils-1.2.1-rc3.patch ---
diff --git a/support/include/nfs/nfs.h b/support/include/nfs/nfs.h
index 00b0028..a64eb0a 100644
--- a/support/include/nfs/nfs.h
+++ b/support/include/nfs/nfs.h
@@ -42,14 +42,21 @@ struct nfs_fh_old {
 #define NFSCTL_GETFD		7	/* get an fh by path (used by mountd) */
 #define NFSCTL_GETFS		8	/* get an fh by path with max size (used by mountd) */
 
+#define NFSCTL_UDPBIT		      (1 << (17 - 1))
+#define NFSCTL_TCPBIT		      (1 << (18 - 1))
+
 #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_UDPUNSET(_cltbits)     ((_cltbits) &= ~NFSCTL_UDPBIT) 
+#define NFSCTL_TCPUNSET(_cltbits)     ((_cltbits) &= ~NFSCTL_TCPBIT) 
 
 #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_UDPISSET(_cltbits)     ((_cltbits) & NFSCTL_UDPBIT) 
+#define NFSCTL_TCPISSET(_cltbits)     ((_cltbits) & NFSCTL_TCPBIT) 
+
+#define NFSCTL_UDPSET(_cltbits)       ((_cltbits) |= NFSCTL_UDPBIT)
+#define NFSCTL_TCPSET(_cltbits)       ((_cltbits) |= NFSCTL_TCPBIT)
 
+#define NFSCTL_ANYPROTO(_cltbits)     ((_cltbits) & (NFSCTL_UDPBIT | NFSCTL_TCPBIT))
 #define NFSCTL_ALLBITS (~0)
 
 /* SVC */
diff --git a/support/include/nfslib.h b/support/include/nfslib.h
index ae98650..537a31e 100644
--- a/support/include/nfslib.h
+++ b/support/include/nfslib.h
@@ -130,7 +130,6 @@ int			wildmat(char *text, char *pattern);
  * nfsd library functions.
  */
 int			nfsctl(int, struct nfsctl_arg *, union nfsctl_res *);
-int			nfssvc(int port, int nrservs, unsigned int versbits, int minorvers4, 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/nfs/Makefile.am b/support/nfs/Makefile.am
index 86f52a1..096f56d 100644
--- a/support/nfs/Makefile.am
+++ b/support/nfs/Makefile.am
@@ -2,7 +2,7 @@
 
 noinst_LIBRARIES = libnfs.a
 libnfs_a_SOURCES = exports.c rmtab.c xio.c rpcmisc.c rpcdispatch.c \
-		   xlog.c xcommon.c wildmat.c nfssvc.c nfsclient.c \
+		   xlog.c xcommon.c wildmat.c nfsclient.c \
 		   nfsexport.c getfh.c nfsctl.c rpc_socket.c getport.c \
 		   svc_socket.c cacheio.c closeall.c nfs_mntent.c
 
diff --git a/support/nfs/nfssvc.c b/support/nfs/nfssvc.c
deleted file mode 100644
index 33c15a7..0000000
--- a/support/nfs/nfssvc.c
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * support/nfs/nfssvc.c
- *
- * Run an NFS daemon.
- *
- * Copyright (C) 1995, 1996 Olaf Kirch <okir at monad.swb.de>
- */
-
-#ifdef HAVE_CONFIG_H
-#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, n, on=1;
-	char buf[BUFSIZ];
-	int udpfd = -1, tcpfd = -1;
-	struct sockaddr_in sin;
-
-	fd = open(NFSD_PORTS_FILE, O_RDONLY);
-	if (fd < 0)
-		return;
-	n = read(fd, buf, BUFSIZ);
-	close(fd);
-	if (n != 0)
-		return;
-	/* there are no ports currently open, so it is safe to
-	 * try to open some and pass them through.
-	 * Note: If the user explicitly asked for 'udp', then
-	 * we should probably check if that is open, and should
-	 * open it if not.  However we don't yet.  All sockets
-	 * have to be opened when the first daemon is started.
-	 */
-	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: writing 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: writing fds to kernel failed: errno %d (%s)", 
-			       errno, strerror(errno));
-		}
-	}
-	close(fd);
-
-	return;
-}
-static void
-nfssvc_versbits(unsigned int ctlbits, int minorvers4)
-{
-	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);
-	}
-	n = minorvers4 >= 0 ? minorvers4 : -minorvers4;
-	if (n >= NFSD_MINMINORVERS4 && n <= NFSD_MAXMINORVERS4)
-		    off += snprintf(ptr+off, BUFSIZ - off, "%c4.%d",
-				    minorvers4 > 0 ? '+' : '-',
-				    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, unsigned int versbits, int minorvers4,
-	unsigned protobits, char *haddr)
-{
-	struct nfsctl_arg	arg;
-	int fd;
-
-	/* Note: must set versions before fds so that
-	 * the ports get registered with portmap against correct
-	 * versions
-	 */
-	nfssvc_versbits(versbits, minorvers4);
-	nfssvc_setfds(port, protobits, haddr);
-
-	fd = open(NFSD_THREAD_FILE, O_WRONLY);
-	if (fd < 0)
-		fd = open("/proc/fs/nfs/threads", O_WRONLY);
-	if (fd >= 0) {
-		/* 2.5+ kernel with nfsd filesystem mounted.
-		 * Just write the number in.
-		 * Cannot handle port number yet, but does anyone care?
-		 */
-		char buf[20];
-		int n;
-		snprintf(buf, 20,"%d\n", nrservs);
-		n = write(fd, buf, strlen(buf));
-		close(fd);
-		if (n != strlen(buf))
-			return -1;
-		else
-			return 0;
-	}
-
-	arg.ca_version = NFSCTL_VERSION;
-	arg.ca_svc.svc_nthreads = nrservs;
-	arg.ca_svc.svc_port = port;
-	return nfsctl(NFSCTL_SVC, &arg, NULL);
-}
diff --git a/utils/nfsd/Makefile.am b/utils/nfsd/Makefile.am
index 445e3fd..c4c6fb0 100644
--- a/utils/nfsd/Makefile.am
+++ b/utils/nfsd/Makefile.am
@@ -7,10 +7,8 @@ RPCPREFIX	= rpc.
 KPREFIX		= @kprefix@
 sbin_PROGRAMS	= nfsd
 
-nfsd_SOURCES = nfsd.c
-nfsd_LDADD = ../../support/export/libexport.a \
-	     ../../support/nfs/libnfs.a \
-	     ../../support/misc/libmisc.a
+nfsd_SOURCES = nfsd.c nfssvc.c
+nfsd_LDADD = ../../support/nfs/libnfs.a
 
 MAINTAINERCLEANFILES = Makefile.in
 
diff --git a/utils/nfsd/nfsd.c b/utils/nfsd/nfsd.c
index e3c0094..650c593 100644
--- a/utils/nfsd/nfsd.c
+++ b/utils/nfsd/nfsd.c
@@ -18,13 +18,14 @@
 #include <string.h>
 #include <errno.h>
 #include <getopt.h>
-#include <syslog.h>
 #include <netdb.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
 #include "nfslib.h"
+#include "nfssvc.h"
+#include "xlog.h"
 
 static void	usage(const char *);
 
@@ -37,47 +38,116 @@ static struct option longopts[] =
 	{ "no-udp", 0, 0, 'U' },
 	{ "port", 1, 0, 'P' },
 	{ "port", 1, 0, 'p' },
+	{ "debug", 0, 0, 'd' },
+	{ "syslog", 0, 0, 's' },
 	{ NULL, 0, 0, 0 }
 };
-unsigned int protobits = NFSCTL_ALLBITS;
-unsigned int versbits = NFSCTL_ALLBITS;
-int minorvers4 = NFSD_MAXMINORVERS4;		/* nfsv4 minor version */
-char *haddr = NULL;
+
+/* given a family and ctlbits, disable any that aren't listed in netconfig */
+#ifdef HAVE_LIBTIRPC
+static void
+nfsd_enable_protos(unsigned int *proto4, unsigned int *proto6)
+{
+	struct netconfig *nconf;
+	unsigned int *famproto;
+	void *handle;
+
+	xlog(D_GENERAL, "Checking netconfig for visible protocols.");
+
+	handle = setnetconfig();
+	while((nconf = getnetconfig(handle))) {
+		if (!(nconf->nc_flag & NC_VISIBLE))
+			continue;
+
+		if (!strcmp(nconf->nc_protofmly, NC_INET))
+			famproto = proto4;
+		else if (!strcmp(nconf->nc_protofmly, NC_INET6))
+			famproto = proto6;
+		else
+			continue;
+
+		if (!strcmp(nconf->nc_proto, NC_TCP))
+			NFSCTL_TCPSET(*famproto);
+		else if (!strcmp(nconf->nc_proto, NC_UDP))
+			NFSCTL_UDPSET(*famproto);
+
+		xlog(D_GENERAL, "Enabling %s %s.", nconf->nc_protofmly,
+			nconf->nc_proto);
+	}
+	endnetconfig(handle);
+	return;
+}
+#else /* HAVE_LIBTIRPC */
+static void
+nfsd_enable_protos(unsigned int *proto4, unsigned int *proto6)
+{
+	/* Enable all IPv4 protocols if no TIRPC support */
+	*proto4 = NFSCTL_ALLBITS;
+	*proto6 = 0;
+}
+#endif /* HAVE_LIBTIRPC */
 
 int
 main(int argc, char **argv)
 {
-	int	count = 1, c, error, port, fd, found_one;
-	struct servent *ent;
-	struct hostent *hp;
-	char *p;
-
-	ent = getservbyname ("nfs", "udp");
-	if (ent != NULL)
-		port = ntohs (ent->s_port);
-	else
-		port = 2049;
-
-	while ((c = getopt_long(argc, argv, "H:hN:p:P:TU", longopts, NULL)) != EOF) {
+	int	count = 1, c, error = 0, portnum = 0, fd, found_one;
+	char *p, *progname, *port;
+	char *haddr = NULL;
+	int	socket_up = 0;
+	int minorvers4 = NFSD_MAXMINORVERS4;	/* nfsv4 minor version */
+	unsigned int versbits = NFSCTL_ALLBITS;
+	unsigned int protobits = NFSCTL_ALLBITS;
+	unsigned int proto4 = 0;
+	unsigned int proto6 = 0;
+
+	progname = strdup(basename(argv[0]));
+	if (!progname) {
+		fprintf(stderr, "%s: unable to allocate memory.\n", argv[0]);
+		exit(1);
+	}
+
+	port = strdup("nfs");
+	if (!port) {
+		fprintf(stderr, "%s: unable to allocate memory.\n", progname);
+		exit(1);
+	}
+
+	xlog_syslog(0);
+	xlog_stderr(1);
+
+	while ((c = getopt_long(argc, argv, "dH:hN:p:P:sTU", longopts, NULL)) != EOF) {
 		switch(c) {
+		case 'd':
+			xlog_config(D_ALL, 1);
+			break;
 		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]);
+			/*
+			 * for now, this only handles one -H option. Use the
+			 * last one specified.
+			 */
+			free(haddr);
+			haddr = strdup(optarg);
+			if (!haddr) {
+				fprintf(stderr, "%s: unable to allocate "
+					"memory.\n", progname);
+				exit(1);
 			}
 			break;
 		case 'P':	/* XXX for nfs-server compatibility */
 		case 'p':
-			port = atoi(optarg);
-			if (port <= 0 || port > 65535) {
+			/* only the last -p option has any effect */
+			portnum = atoi(optarg);
+			if (portnum <= 0 || portnum > 65535) {
 				fprintf(stderr, "%s: bad port number: %s\n",
-					argv[0], optarg);
-				usage(argv [0]);
+					progname, optarg);
+				usage(progname);
+			}
+			free(port);
+			port = strdup(optarg);
+			if (!port) {
+				fprintf(stderr, "%s: unable to allocate "
+						"memory.\n", progname);
+				exit(1);
 			}
 			break;
 		case 'N':
@@ -96,80 +166,133 @@ main(int argc, char **argv)
 				exit(1);
 			}
 			break;
+		case 's':
+			xlog_syslog(1);
+			xlog_stderr(0);
+			break;
 		case 'T':
-				NFSCTL_TCPUNSET(protobits);
-				break;
+			NFSCTL_TCPUNSET(protobits);
+			break;
 		case 'U':
-				NFSCTL_UDPUNSET(protobits);
-				break;
+			NFSCTL_UDPUNSET(protobits);
+			break;
 		default:
 			fprintf(stderr, "Invalid argument: '%c'\n", c);
 		case 'h':
-			usage(argv[0]);
+			usage(progname);
 		}
 	}
-	/*
-	 * Do some sanity checking, if the ctlbits are set
-	 */
-	if (!NFSCTL_UDPISSET(protobits) && !NFSCTL_TCPISSET(protobits)) {
-		fprintf(stderr, "invalid protocol specified\n");
-		exit(1);
+
+	if (optind < argc) {
+		if ((count = atoi(argv[optind])) < 0) {
+			/* insane # of servers */
+			fprintf(stderr,
+				"%s: invalid server count (%d), using 1\n",
+				argv[0], count);
+			count = 1;
+		} else if (count == 0) {
+			/*
+			 * don't bother setting anything else if the threads
+			 * are coming down anyway.
+			 */
+			socket_up = 1;
+			goto set_threads;
+		}
 	}
+
+	xlog_open(progname);
+
+	nfsd_enable_protos(&proto4, &proto6);
+
+	if (!NFSCTL_TCPISSET(protobits)) {
+		NFSCTL_TCPUNSET(proto4);
+		NFSCTL_TCPUNSET(proto6);
+	}
+
+	if (!NFSCTL_UDPISSET(protobits)) {
+		NFSCTL_UDPUNSET(proto4);
+		NFSCTL_UDPUNSET(proto6);
+	}
+
+	/* make sure that at least one version is enabled */
 	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");
+		xlog(L_ERROR, "no version specified");
 		exit(1);
 	}			
 
-	if (NFSCTL_VERISSET(versbits, 4) && !NFSCTL_TCPISSET(protobits)) {
-		fprintf(stderr, "version 4 requires the TCP protocol\n");
+	if (NFSCTL_VERISSET(versbits, 4) &&
+	    !NFSCTL_TCPISSET(proto4) &&
+	    !NFSCTL_TCPISSET(proto6)) {
+		xlog(L_ERROR, "version 4 requires the TCP protocol");
 		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",
-			argv [0], NFS_STATEDIR, strerror(errno));
+		xlog(L_ERROR, "chdir(%s) failed: %m", NFS_STATEDIR);
 		exit(1);
 	}
 
-	if (optind < argc) {
-		if ((count = atoi(argv[optind])) < 0) {
-			/* insane # of servers */
-			fprintf(stderr,
-				"%s: invalid server count (%d), using 1\n",
-				argv[0], count);
-			count = 1;
-		}
+	/* can only change number of threads if nfsd is already up */
+	if (nfssvc_inuse()) {
+		socket_up = 1;
+		goto set_threads;
 	}
-	/* KLUDGE ALERT:
-	   Some kernels let nfsd kernel threads inherit open files
-	   from the program that spawns them (i.e. us).  So close
-	   everything before spawning kernel threads.  --Chip */
+
+	/*
+	 * must set versions before the fd's so that the right versions get
+	 * registered with rpcbind. Note that on older kernels w/o the right
+	 * interfaces, these are a no-op.
+	 */
+	nfssvc_setvers(versbits, minorvers4);
+ 
+	error = nfssvc_set_sockets(AF_INET, proto4, haddr, port);
+	if (!error)
+		socket_up = 1;
+
+#ifdef IPV6_SUPPORTED
+	error = nfssvc_set_sockets(AF_INET6, proto6, haddr, port);
+	if (!error)
+		socket_up = 1;
+#endif /* IPV6_SUPPORTED */
+
+set_threads:
+	/* don't start any threads if unable to hand off any sockets */
+	if (!socket_up) {
+		xlog(L_ERROR, "unable to set any sockets for nfsd");
+		goto out;
+	}
+	error = 0;
+
+	/*
+	 * KLUDGE ALERT:
+	 * Some kernels let nfsd kernel threads inherit open files
+	 * from the program that spawns them (i.e. us).  So close
+	 * everything before spawning kernel threads.  --Chip
+	 */
 	fd = open("/dev/null", O_RDWR);
 	if (fd == -1)
-		perror("/dev/null");
+		xlog(L_ERROR, "Unable to open /dev/null: %m");
 	else {
+		/* switch xlog output to syslog since stderr is being closed */
+		xlog_syslog(1);
+		xlog_stderr(0);
 		(void) dup2(fd, 0);
 		(void) dup2(fd, 1);
 		(void) dup2(fd, 2);
 	}
 	closeall(3);
 
-	openlog("nfsd", LOG_PID, LOG_DAEMON);
-	if ((error = nfssvc(port, count, versbits, minorvers4, protobits, haddr)) < 0) {
-		int e = errno;
-		syslog(LOG_ERR, "nfssvc: %s", strerror(e));
-		closelog();
-	}
-
+	if ((error = nfssvc_threads(portnum, count)) < 0)
+		xlog(L_ERROR, "error starting threads: errno %d (%m)", errno);
+out:
+	free(port);
+	free(haddr);
+	free(progname);
 	return (error != 0);
 }
 
@@ -177,7 +300,7 @@ static void
 usage(const char *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", 
+		"%s [-d|--debug] [-H hostname] [-p|-P|--port port] [-N|--no-nfs-version version ] [-s|--syslog] [-T|--no-tcp] [-U|--no-udp] nrservs\n", 
 		prog);
 	exit(2);
 }
diff --git a/utils/nfsd/nfsd.man b/utils/nfsd/nfsd.man
index 4eb3e21..d8988d2 100644
--- a/utils/nfsd/nfsd.man
+++ b/utils/nfsd/nfsd.man
@@ -13,8 +13,9 @@ The
 program implements the user level part of the NFS service. The
 main functionality is handled by the
 .B nfsd
-kernel module; the user space program merely starts the specified
-number of kernel threads.
+kernel module. The user space program merely specifies what sort of sockets
+the kernel service should listen on, what NFS versions it should support, and
+how many kernel threads it should use.
 .P
 The
 .B rpc.mountd
@@ -22,6 +23,9 @@ server provides an ancillary service needed to satisfy mount requests
 by NFS clients.
 .SH OPTIONS
 .TP
+.B \-d " or " \-\-debug
+enable logging of debugging messages
+.TP
 .B \-H " or " \-\-host  hostname
 specify a particular hostname (or address) that NFS requests will
 be accepted on. By default,
@@ -45,6 +49,14 @@ 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 \-s " or " \-\-syslog
+By default,
+.B rpc.nfsd
+logs error messages (and debug messages, if enabled) to stderr. This option makes 
+.B rpc.nfsd
+log these messages to syslog instead. Note that errors encountered during
+option processing will still be logged to stderr regardless of this option.
+.TP
 .B \-T " or " \-\-no-tcp
 Disable 
 .B rpc.nfsd 
@@ -75,12 +87,19 @@ In particular
 .B rpc.nfsd 0
 will stop all threads and thus close any open connections.
 
+.SH NOTES
+If the program is built with TI-RPC support, it will enable any protocol and
+address family combinations that are marked visible in the
+.B netconfig
+database.
+
 .SH SEE ALSO
 .BR rpc.mountd (8),
 .BR exports (5),
 .BR exportfs (8),
 .BR rpc.rquotad (8),
-.BR nfsstat (8).
+.BR nfsstat (8),
+.BR netconfig(5).
 .SH AUTHOR
 Olaf Kirch, Bill Hawes, H. J. Lu, G. Allan Morris III,
 and a host of others.
diff --git a/utils/nfsd/nfssvc.c b/utils/nfsd/nfssvc.c
new file mode 100644
index 0000000..ee862b2
--- /dev/null
+++ b/utils/nfsd/nfssvc.c
@@ -0,0 +1,289 @@
+/*
+ * utils/nfsd/nfssvc.c
+ *
+ * Run an NFS daemon.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir at monad.swb.de>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "nfslib.h"
+#include "xlog.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"
+
+/*
+ * declaring a common static scratch buffer here keeps us from having to
+ * continually thrash the stack. The value of 128 bytes here is really just a
+ * SWAG and can be increased if necessary. It ought to be enough for the
+ * routines below however.
+ */
+char buf[128];
+
+/*
+ * Are there already sockets configured? If not, then it is safe to try to
+ * open some and pass them through.
+ *
+ * Note: If the user explicitly asked for 'udp', then we should probably check
+ * if that is open, and should open it if not. However we don't yet. All
+ * sockets have to be opened when the first daemon is started.
+ */
+int
+nfssvc_inuse(void)
+{
+	int fd, n;
+
+	fd = open(NFSD_PORTS_FILE, O_RDONLY);
+
+	/* problem opening file, assume that nothing is configured */
+	if (fd < 0)
+		return 0;
+
+	n = read(fd, buf, sizeof(buf));
+	close(fd);
+
+	xlog(D_GENERAL, "knfsd is currently %s", (n > 0) ? "up" : "down");
+
+	return (n > 0);
+}
+
+static int
+nfssvc_setfds(const struct addrinfo *hints, const char *node, const char *port)
+{
+	int fd, on = 1, fac = L_ERROR;
+	int sockfd = -1, rc = 0;
+	struct addrinfo *addrhead = NULL, *addr;
+	char *proto, *family;
+
+	/*
+	 * if file can't be opened, then assume that it's not available and
+	 * that the caller should just fall back to the old nfsctl interface
+ 	 */
+	fd = open(NFSD_PORTS_FILE, O_WRONLY);
+	if (fd < 0)
+		return 0;
+
+	switch(hints->ai_family) {
+	case AF_INET:
+		family = "inet";
+		break;
+#ifdef IPV6_SUPPORTED
+	case AF_INET6:
+		family = "inet6";
+		break;
+#endif /* IPV6_SUPPORTED */
+	default:
+		xlog(L_ERROR, "Unknown address family specified: %d\n",
+				hints->ai_family);
+		rc = EAFNOSUPPORT;
+		goto error;
+	}
+
+	rc = getaddrinfo(node, port, hints, &addrhead);
+	if (rc == EAI_NONAME && !strcmp(port, "nfs")) {
+		snprintf(buf, sizeof(buf), "%d", NFS_PORT);
+		rc = getaddrinfo(node, buf, hints, &addrhead);
+	}
+
+	if (rc != 0) {
+		xlog(L_ERROR, "unable to resolve %s:%s to %s address: "
+				"%s", node ? node : "ANYADDR", port, family,
+				rc == EAI_SYSTEM ? strerror(errno) :
+					gai_strerror(rc));
+		goto error;
+	}
+
+	addr = addrhead;
+	while(addr) {
+		/* skip non-TCP / non-UDP sockets */
+		switch(addr->ai_protocol) {
+		case IPPROTO_UDP:
+			proto = "UDP";
+			break;
+		case IPPROTO_TCP:
+			proto = "TCP";
+			break;
+		default:
+			addr = addr->ai_next;
+			continue;
+		}
+
+		xlog(D_GENERAL, "Creating %s %s socket.", family, proto);
+
+		/* open socket and prepare to hand it off to kernel */
+		sockfd = socket(addr->ai_family, addr->ai_socktype,
+				addr->ai_protocol);
+		if (sockfd < 0) {
+			xlog(L_ERROR, "unable to create %s %s socket: "
+				"errno %d (%m)", family, proto, errno);
+			rc = errno;
+			goto error;
+		}
+#ifdef IPV6_SUPPORTED
+		if (addr->ai_family == AF_INET6 &&
+		    setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on))) {
+			xlog(L_ERROR, "unable to set IPV6_V6ONLY: "
+				"errno %d (%m)\n", errno);
+			rc = errno;
+			goto error;
+		}
+#endif /* IPV6_SUPPORTED */
+		if (addr->ai_protocol == IPPROTO_TCP &&
+		    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) {
+			xlog(L_ERROR, "unable to set SO_REUSEADDR on %s "
+				"socket: errno %d (%m)", family, errno);
+			rc = errno;
+			goto error;
+		}
+		if (bind(sockfd, addr->ai_addr, addr->ai_addrlen)) {
+			xlog(L_ERROR, "unable to bind %s %s socket: "
+				"errno %d (%m)", family, proto, errno);
+			rc = errno;
+			goto error;
+		}
+		if (addr->ai_protocol == IPPROTO_TCP && listen(sockfd, 64)) {
+			xlog(L_ERROR, "unable to create listening socket: "
+				"errno %d (%m)", errno);
+			rc = errno;
+			goto error;
+		}
+
+		if (fd < 0)
+			fd = open(NFSD_PORTS_FILE, O_WRONLY);
+
+		if (fd < 0) {
+			xlog(L_ERROR, "couldn't open ports file: errno "
+				      "%d (%m)", errno);
+			goto error;
+		}
+
+		snprintf(buf, sizeof(buf), "%d\n", sockfd); 
+		if (write(fd, buf, strlen(buf)) != strlen(buf)) {
+			/*
+			 * this error may be common on older kernels that don't
+			 * support IPv6, so turn into a debug message.
+			 */
+			if (errno == EAFNOSUPPORT)
+				fac = D_ALL;
+			xlog(fac, "writing fd to kernel failed: errno %d (%m)",
+				  errno);
+			rc = errno;
+			goto error;
+		}
+		close(fd);
+		close(sockfd);
+		sockfd = fd = -1;
+		addr = addr->ai_next;
+	}
+error:
+	if (fd >= 0)
+		close(fd);
+	if (sockfd >= 0)
+		close(sockfd);
+	if (addrhead)
+		freeaddrinfo(addrhead);
+	return rc;
+}
+
+int
+nfssvc_set_sockets(const int family, const unsigned int protobits,
+		   const char *host, const char *port)
+{
+	struct addrinfo hints = { .ai_flags = AI_PASSIVE | AI_ADDRCONFIG };
+
+	hints.ai_family = family;
+
+	if (!NFSCTL_ANYPROTO(protobits))
+		return EPROTOTYPE;
+	else if (!NFSCTL_UDPISSET(protobits))
+		hints.ai_protocol = IPPROTO_TCP;
+	else if (!NFSCTL_TCPISSET(protobits))
+		hints.ai_protocol = IPPROTO_UDP;
+
+	return nfssvc_setfds(&hints, host, port);
+}
+
+void
+nfssvc_setvers(unsigned int ctlbits, int minorvers4)
+{
+	int fd, n, off;
+	char *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, sizeof(buf) - off, "+%d ", n);
+		else
+		    off += snprintf(ptr+off, sizeof(buf) - off, "-%d ", n);
+	}
+	n = minorvers4 >= 0 ? minorvers4 : -minorvers4;
+	if (n >= NFSD_MINMINORVERS4 && n <= NFSD_MAXMINORVERS4)
+		    off += snprintf(ptr+off, sizeof(buf) - off, "%c4.%d",
+				    minorvers4 > 0 ? '+' : '-',
+				    n);
+	xlog(D_GENERAL, "Writing version string to kernel: %s", buf);
+	snprintf(ptr+off, sizeof(buf) - off, "\n");
+	if (write(fd, buf, strlen(buf)) != strlen(buf))
+		xlog(L_ERROR, "Setting version failed: errno %d (%m)", errno);
+
+	close(fd);
+
+	return;
+}
+
+int
+nfssvc_threads(unsigned short port, const int nrservs)
+{
+	struct nfsctl_arg	arg;
+	struct servent *ent;
+	ssize_t n;
+	int fd;
+
+	fd = open(NFSD_THREAD_FILE, O_WRONLY);
+	if (fd < 0)
+		fd = open("/proc/fs/nfs/threads", O_WRONLY);
+	if (fd >= 0) {
+		/* 2.5+ kernel with nfsd filesystem mounted.
+		 * Just write the number of threads.
+		 */
+		snprintf(buf, sizeof(buf), "%d\n", nrservs);
+		n = write(fd, buf, strlen(buf));
+		close(fd);
+		if (n != strlen(buf))
+			return -1;
+		else
+			return 0;
+	}
+
+	if (!port) {
+		ent = getservbyname("nfs", "udp");
+		if (ent != NULL)
+			port = ntohs(ent->s_port);
+		else
+			port = NFS_PORT;
+	}
+
+	arg.ca_version = NFSCTL_VERSION;
+	arg.ca_svc.svc_nthreads = nrservs;
+	arg.ca_svc.svc_port = port;
+	return nfsctl(NFSCTL_SVC, &arg, NULL);
+}
diff --git a/utils/nfsd/nfssvc.h b/utils/nfsd/nfssvc.h
new file mode 100644
index 0000000..0c69bd6
--- /dev/null
+++ b/utils/nfsd/nfssvc.h
@@ -0,0 +1,27 @@
+/*
+ *   utils/nfsd/nfssvc.h -- nfs service control routines for rpc.nfsd
+ *
+ *   Copyright (C) 2009 Red Hat, Inc <nfs at redhat.com>.
+ *   Copyright (C) 2009 Jeff Layton <jlayton at redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+int	nfssvc_inuse(void);
+int	nfssvc_set_sockets(const int family, const unsigned int protobits,
+			   const char *host, const char *port);
+void	nfssvc_setvers(unsigned int ctlbits, int minorvers4);
+int	nfssvc_threads(unsigned short port, int nrservs);


Index: nfs-utils.spec
===================================================================
RCS file: /cvs/pkgs/rpms/nfs-utils/devel/nfs-utils.spec,v
retrieving revision 1.238
retrieving revision 1.239
diff -u -p -r1.238 -r1.239
--- nfs-utils.spec	28 Jul 2009 12:33:38 -0000	1.238
+++ nfs-utils.spec	16 Aug 2009 20:03:23 -0000	1.239
@@ -2,7 +2,7 @@ Summary: NFS utilities and supporting cl
 Name: nfs-utils
 URL: http://sourceforge.net/projects/nfs
 Version: 1.2.0
-Release: 8%{?dist}
+Release: 9%{?dist}
 Epoch: 1
 
 # group all 32bit related archs
@@ -25,7 +25,7 @@ Patch02: nfs-utils-1.1.0-exp-subtree-war
 Patch100: nfs-utils-1.2.1-rc1.patch
 Patch101: nfs-utils-1.2.1-rc2.patch
 Patch102: nfs-utils-1.2.0-proots-rel5.patch
-Patch103: nfs-utils-1.2.0-nfsd-41vers.patch
+Patch103: nfs-utils-1.2.1-rc3.patch
 
 Group: System Environment/Daemons
 Provides: exportfs    = %{epoch}:%{version}-%{release}
@@ -249,35 +249,44 @@ fi
 %attr(4755,root,root)   /sbin/umount.nfs4
 
 %changelog
-* Tue Jul 28 2009 <steved at redhat.com> 1.2.0-8
+* Fri Aug 14 2009 Steve Dickson <steved at redhat.com> 1.2.0-9
+- Added upstream 1.2.1-rc3 patch
+  - Add IPv6 support to nfsd
+  - Allow nfssvc_setfds to properly deal with AF_INET6
+  - Convert nfssvc_setfds to use getaddrinfo
+  - Move check for active knfsd to helper function
+  - Declare a static common buffer for nfssvc.c routine
+  - Convert rpc.nfsd to use xlog() and add --debug and --syslog options
+
+* Tue Jul 28 2009 Steve Dickson <steved at redhat.com> 1.2.0-8
 - Fixed 4.1 versioning problem (bz 512377)
 
-* Wed Jul 15 2009 <steved at redhat.com> 1.2.0-7
+* Wed Jul 15 2009 Steve Dickson <steved at redhat.com> 1.2.0-7
 - Added upstream 1.2.1-rc2 patch
   - A large number of mount command changes.
 
-* Mon Jul 13 2009 <steved at redhat.com> 1.2.0-6
+* Mon Jul 13 2009 Steve Dickson <steved at redhat.com> 1.2.0-6
 - Added NFSD v4 dynamic pseudo root patch which allows
   NFS v3 exports to be mounted by v4 clients.
 
-* Mon Jun 29 2009 <steved at redhat.com> 1.2.0-5
+* Mon Jun 29 2009 Steve Dickson <steved at redhat.com> 1.2.0-5
 - Stopped rpc.idmapd from spinning (bz 508221)
 
-* Mon Jun 22 2009 <steved at redhat.com> 1.2.0-4
+* Mon Jun 22 2009 Steve Dickson <steved at redhat.com> 1.2.0-4
 - Added upstream 1.2.1-rc1 patch 
   - Fix to check in closeall()
   - Make --enable-tirpc the default
   - Set all verbose types in gssd daemons
   - Retry exports if getfh() fails
 
-* Wed Jun 10 2009 <steved at redhat.com> 1.2.0-3
+* Wed Jun 10 2009 Steve Dickson <steved at redhat.com> 1.2.0-3
 - Updated init scripts to add dependencies
   on other system facilities (bz 475133)
 
-* Wed Jun 10 2009 <steved at redhat.com> 1.2.0-2
+* Wed Jun 10 2009 Steve Dickson <steved at redhat.com> 1.2.0-2
 - nfsnobody gid is wrong (bz 485379)
 
-* Tue Jun  2 2009 <steved at redhat.com> 1.2.0-1
+* Tue Jun  2 2009 Steve Dickson <steved at redhat.com> 1.2.0-1
 - Updated to latest upstream release: 1.2.0
 
 * Tue May 19 2009 Tom "spot" Callaway <tcallawa at redhat.com> 1.1.6-4


--- nfs-utils-1.2.0-nfsd-41vers.patch DELETED ---




More information about the fedora-extras-commits mailing list