Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 3 Apr 2001 18:39:50 +0200 (CEST)
From:      bg@sics.se
To:        FreeBSD-gnats-submit@freebsd.org
Cc:        bg@sics.se
Subject:   misc/26320: mountd breaks IRIX automounter
Message-ID:  <200104031639.f33Gdoa09283@bg.sics.se>

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

>Number:         26320
>Category:       misc
>Synopsis:       mountd breaks IRIX automounter
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Apr 03 09:40:00 PDT 2001
>Closed-Date:
>Last-Modified:
>Originator:     Bjoern Groenvall
>Release:        FreeBSD 4.2-RELEASE i386
>Organization:
SICS
>Environment:

NFS servers running
FreeBSD 3.5-RELEASE or FreeBSD 4.2-RELEASE

>Description:

This problem really stems from a poorly designed mount protocol. When
using ONC/RPC over UDP, RPC requests and responses are limited to
8kbytes of data. If a RPC response can not fit into that limited space
the RPC will fail. The mountd protocol has a procedure
MOUNTPROC_EXPORT that returns a list of all exported file systems and
which machines are allowed to import it. If a server has many clients
and exports many file systems this RPC reply will no longer fit into
8kbytes!

Fortunately, only the list of exported file systems is relevant to
programs such as the automounter. It is thus possible to return an
abbreviated reply that uses a placeholder for the hosts lists.

>How-To-Repeat:

Set up a FreeBSD NFS file server and export many file systems to many
hosts. Verify that the output from showmount -e your.nfs.server is
really long (longer than 8k).

From a IRIX host, try ls /hosts/your.file.server/. The ls will
eventually fail. On the file server you will find a syslog entry
"can't send reply".

>Fix:

The fix below first try to send a regular RPC reply, only when this
fails, an abbreviated reply is sent. The fix has been verified on 3.5
and 4.2 hosts.

--- mountd.c.ORIG	Tue Nov 23 00:03:59 1999
+++ mountd.c	Mon Apr  2 18:43:17 2001
@@ -191,11 +191,12 @@
 void	nextfield __P((char **, char **));
 void	out_of_mem __P((void));
 void	parsecred __P((char *, struct ucred *));
-int	put_exlist __P((struct dirlist *, XDR *, struct dirlist *, int *));
+int	put_exlist __P((struct dirlist *, XDR *, struct dirlist *, int *,int));
 int	scan_tree __P((struct dirlist *, u_int32_t));
 static void usage __P((void));
 int	xdr_dir __P((XDR *, char *));
 int	xdr_explist __P((XDR *, caddr_t));
+int	xdr_explist_brief __P((XDR *, caddr_t));
 int	xdr_fhs __P((XDR *, caddr_t));
 int	xdr_mlist __P((XDR *, caddr_t));
 
@@ -542,7 +543,8 @@
 		return;
 	case RPCMNT_EXPORT:
 		if (!svc_sendreply(transp, xdr_explist, (caddr_t)NULL))
-			syslog(LOG_ERR, "can't send reply");
+			if (!svc_sendreply(transp, xdr_explist_brief, (caddr_t)NULL))
+				syslog(LOG_ERR, "can't send reply");
 		if (log)
 			syslog(LOG_NOTICE,
 			    "export request succeeded from %s",
@@ -630,9 +632,10 @@
  * Xdr conversion for export list
  */
 int
-xdr_explist(xdrsp, cp)
+xdr_explist_common(xdrsp, cp, brief)
 	XDR *xdrsp;
 	caddr_t cp;
+	int brief;
 {
 	struct exportlist *ep;
 	int false = 0;
@@ -645,11 +648,12 @@
 	ep = exphead;
 	while (ep) {
 		putdef = 0;
-		if (put_exlist(ep->ex_dirl, xdrsp, ep->ex_defdir, &putdef))
+		if (put_exlist(ep->ex_dirl, xdrsp, ep->ex_defdir,
+			       &putdef, brief))
 			goto errout;
 		if (ep->ex_defdir && putdef == 0 &&
 			put_exlist(ep->ex_defdir, xdrsp, (struct dirlist *)NULL,
-			&putdef))
+			&putdef, brief))
 			goto errout;
 		ep = ep->ex_next;
 	}
@@ -667,11 +671,12 @@
  * directory paths.
  */
 int
-put_exlist(dp, xdrsp, adp, putdefp)
+put_exlist(dp, xdrsp, adp, putdefp, brief)
 	struct dirlist *dp;
 	XDR *xdrsp;
 	struct dirlist *adp;
 	int *putdefp;
+	int brief;
 {
 	struct grouplist *grp;
 	struct hostlist *hp;
@@ -681,7 +686,7 @@
 	char *strp;
 
 	if (dp) {
-		if (put_exlist(dp->dp_left, xdrsp, adp, putdefp))
+		if (put_exlist(dp->dp_left, xdrsp, adp, putdefp, brief))
 			return (1);
 		if (!xdr_bool(xdrsp, &true))
 			return (1);
@@ -692,7 +697,13 @@
 			gotalldir = 1;
 			*putdefp = 1;
 		}
-		if ((dp->dp_flag & DP_DEFSET) == 0 &&
+		if (brief) {
+			if (!xdr_bool(xdrsp, &true))
+				return (1);
+			strp = "(...)";
+			if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN))
+				return (1);
+		} else if ((dp->dp_flag & DP_DEFSET) == 0 &&
 		    (gotalldir == 0 || (adp->dp_flag & DP_DEFSET) == 0)) {
 			hp = dp->dp_hosts;
 			while (hp) {
@@ -721,10 +732,26 @@
 		}
 		if (!xdr_bool(xdrsp, &false))
 			return (1);
-		if (put_exlist(dp->dp_right, xdrsp, adp, putdefp))
+		if (put_exlist(dp->dp_right, xdrsp, adp, putdefp, brief))
 			return (1);
 	}
 	return (0);
+}
+
+int
+xdr_explist(xdrsp, cp)
+	XDR *xdrsp;
+	caddr_t cp;
+{
+	return xdr_explist_common(xdrsp, cp, 0 /* !brief */);
+}
+
+int
+xdr_explist_brief(xdrsp, cp)
+	XDR *xdrsp;
+	caddr_t cp;
+{
+	return xdr_explist_common(xdrsp, cp, 1 /* brief */);
 }
 
 #define LINESIZ	10240
>Release-Note:
>Audit-Trail:
>Unformatted:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




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