Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 7 May 2013 13:13:06 +0300
From:      Andrey Simonenko <simon@comsys.ntu-kpi.kiev.ua>
To:        FreeBSD-gnats-submit@freebsd.org
Subject:   bin/178392: Add support for WebNFS mounts to mount_nfs
Message-ID:  <20130507101306.GA56075@pm513-1.comsys.ntu-kpi.kiev.ua>
Resent-Message-ID: <201305071020.r47AK2qa004907@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         178392
>Category:       bin
>Synopsis:       Add support for WebNFS mounts to mount_nfs
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Tue May 07 10:20:00 UTC 2013
>Closed-Date:
>Last-Modified:
>Originator:     Andrey Simonenko
>Release:        FreeBSD 10-CURRENT amd64
>Organization:
>Environment:
>Description:

The following change adds support for WebNFS mounts to mount_nfs.
The new option "public" specifies that WebNFS public filehandle should
be used and default NFS server port number 2049 should be tried first.
If NFS server does respond on this port, then rpcbind is asked for
the correct port number.

WebNFS client and server code was checked with NFSSERVER and NFSCLIENT
kernel options on 10-CURRENT.

>How-To-Repeat:

Export some file system for WebNFS in /etc/exports:

/fs -public 127.0.0.1

Then, try to mount it:

# mount_oldnfs -o nfsv3,public 127.0.0.1:/anything /mnt

With kern/178103 it will be possible to use WebNFS index files (not sure
how to check whether WebNFS multi-component lookups are supported).

>Fix:
diff -ruNp mount_nfs.orig/mount_nfs.8 mount_nfs/mount_nfs.8
--- mount_nfs.orig/mount_nfs.8	2012-12-10 13:20:11.000000000 +0200
+++ mount_nfs/mount_nfs.8	2013-04-30 12:37:55.000000000 +0300
@@ -245,6 +245,10 @@ use a reserved socket port number (see b
 .It Cm port Ns = Ns Aq Ar port_number
 Use specified port number for NFS requests.
 The default is to query the portmapper for the NFS port.
+.It Cm public
+Use
+.Tn WebNFS
+public filehandle.
 .It Cm rdirplus
 Used with NFSV3 to specify that the \fBReaddirPlus\fR RPC should
 be used.
diff -ruNp mount_nfs.orig/mount_nfs.c mount_nfs/mount_nfs.c
--- mount_nfs.orig/mount_nfs.c	2013-03-07 13:19:35.000000000 +0200
+++ mount_nfs/mount_nfs.c	2013-04-30 12:43:30.000000000 +0300
@@ -68,6 +68,7 @@ __FBSDID("$FreeBSD: src/sbin/mount_nfs/m
 #include <errno.h>
 #include <fcntl.h>
 #include <netdb.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -114,6 +115,7 @@ u_char *fh = NULL;
 int fhsize = 0;
 int secflavor = -1;
 int got_principal = 0;
+static bool opt_public = false;
 
 enum mountmode {
 	ANY,
@@ -310,6 +312,11 @@ main(int argc, char *argv[])
 					if (*p || num <= 0)
 						errx(1, "illegal maxgroups value -- %s", val);
 					//set_rpc_maxgrouplist(num);
+				} else if (strcmp(opt, "public") == 0) {
+					opt_public = true;
+					if (portspec == NULL)
+						portspec = "2049";
+					pass_flag_to_nmount=0;
 				}
 				if (pass_flag_to_nmount)
 					build_iovec(&iov, &iovlen, opt, val,
@@ -372,6 +379,9 @@ main(int argc, char *argv[])
 		/* NOTREACHED */
 	}
 
+	if (opt_public && mountmode == V4)
+		errx(1, "WebNFS public filehandle cannot be used with NFSv4");
+
 	spec = *argv++;
 	name = *argv;
 
@@ -946,6 +956,10 @@ tryagain:
 	clp = clnt_tli_create(RPC_ANYFD, nconf, &nfs_nb, NFS_PROGRAM, nfsvers,
 	    0, 0);
 	if (clp == NULL) {
+		if (opt_public && portspec != NULL) {
+			portspec = NULL;
+			goto tryagain;
+		}
 		snprintf(errbuf, sizeof errbuf, "[%s] %s:%s: %s", netid,
 		    hostp, spec, clnt_spcreateerror("nfsd: RPCPROG_NFS"));
 		return (returncode(rpc_createerr.cf_stat,
@@ -1009,41 +1023,45 @@ tryagain:
 		return (TRYRET_SUCCESS);
 	}
 
-	/* Send the MOUNTPROC_MNT RPC to get the root filehandle. */
-	try.tv_sec = 10;
-	try.tv_usec = 0;
-	clp = clnt_tp_create(hostp, MOUNTPROG, mntvers, nconf_mnt);
-	if (clp == NULL) {
-		snprintf(errbuf, sizeof errbuf, "[%s] %s:%s: %s", netid_mnt,
-		    hostp, spec, clnt_spcreateerror("RPCMNT: clnt_create"));
-		return (returncode(rpc_createerr.cf_stat,
-		    &rpc_createerr.cf_error));
-	}
-	clp->cl_auth = authsys_create_default();
-	nfhret.auth = secflavor;
-	nfhret.vers = mntvers;
-	stat = clnt_call(clp, MOUNTPROC_MNT, (xdrproc_t)xdr_dir, spec, 
-			 (xdrproc_t)xdr_fh, &nfhret,
-	    try);
-	auth_destroy(clp->cl_auth);
-	if (stat != RPC_SUCCESS) {
-		if (stat == RPC_PROGVERSMISMATCH && trymntmode == ANY) {
+	if (!opt_public) {
+		/* Send the MOUNTPROC_MNT RPC to get the root filehandle. */
+		try.tv_sec = 10;
+		try.tv_usec = 0;
+		clp = clnt_tp_create(hostp, MOUNTPROG, mntvers, nconf_mnt);
+		if (clp == NULL) {
+			snprintf(errbuf, sizeof errbuf, "[%s] %s:%s: %s",
+			    netid_mnt, hostp, spec,
+			    clnt_spcreateerror("RPCMNT: clnt_create"));
+			return (returncode(rpc_createerr.cf_stat,
+			    &rpc_createerr.cf_error));
+		}
+		clp->cl_auth = authsys_create_default();
+		nfhret.auth = secflavor;
+		nfhret.vers = mntvers;
+		stat = clnt_call(clp, MOUNTPROC_MNT, (xdrproc_t)xdr_dir, spec,
+				 (xdrproc_t)xdr_fh, &nfhret, try);
+		auth_destroy(clp->cl_auth);
+		if (stat != RPC_SUCCESS) {
+			if (stat == RPC_PROGVERSMISMATCH &&
+			    trymntmode == ANY) {
+				clnt_destroy(clp);
+				trymntmode = V2;
+				goto tryagain;
+			}
+			clnt_geterr(clp, &rpcerr);
+			snprintf(errbuf, sizeof errbuf, "[%s] %s:%s: %s",
+			    netid_mnt, hostp, spec,
+			    clnt_sperror(clp, "RPCPROG_MNT"));
 			clnt_destroy(clp);
-			trymntmode = V2;
-			goto tryagain;
+			return (returncode(stat, &rpcerr));
 		}
-		clnt_geterr(clp, &rpcerr);
-		snprintf(errbuf, sizeof errbuf, "[%s] %s:%s: %s", netid_mnt,
-		    hostp, spec, clnt_sperror(clp, "RPCPROG_MNT"));
 		clnt_destroy(clp);
-		return (returncode(stat, &rpcerr));
-	}
-	clnt_destroy(clp);
 
-	if (nfhret.stat != 0) {
-		snprintf(errbuf, sizeof errbuf, "[%s] %s:%s: %s", netid_mnt,
-		    hostp, spec, strerror(nfhret.stat));
-		return (TRYRET_REMOTEERR);
+		if (nfhret.stat != 0) {
+			snprintf(errbuf, sizeof errbuf, "[%s] %s:%s: %s",
+			    netid_mnt, hostp, spec, strerror(nfhret.stat));
+			return (TRYRET_REMOTEERR);
+		}
 	}
 
 	/*
@@ -1052,16 +1070,32 @@ tryagain:
 	 */
 	addrlen = nfs_nb.len;
 	addr = malloc(addrlen);
-	fhsize = nfhret.fhsize;
-	fh = malloc(fhsize);
-	if (addr == NULL || fh == NULL)
+	if (addr == NULL)
 		err(1, "malloc");
 	bcopy(nfs_nb.buf, addr, addrlen);
-	bcopy(nfhret.nfh, fh, fhsize);
+	if (!opt_public) {
+		fhsize = nfhret.fhsize;
+		fh = malloc(fhsize);
+		if (fh == NULL)
+			err(1, "malloc");
+		bcopy(nfhret.nfh, fh, fhsize);
+		secname = sec_num_to_name(nfhret.auth);
+	} else {
+		if (trymntmode == V2) {
+			fhsize = NFS_FHSIZE;
+			fh = malloc(fhsize);
+			if (fh == NULL)
+				err(1, "malloc");
+			memset(fh, 0, fhsize);
+		} else {
+			fhsize = 0;
+			fh = NULL;
+		}
+		secname = sec_num_to_name(secflavor);
+	}
 
 	build_iovec(iov, iovlen, "addr", addr, addrlen);
 	build_iovec(iov, iovlen, "fh", fh, fhsize);
-	secname = sec_num_to_name(nfhret.auth);
 	if (secname)
 		build_iovec(iov, iovlen, "sec", secname, (size_t)-1);
 	if (nfsvers == 3)
>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20130507101306.GA56075>