Subject: bin/3207: showmount(8) uses RPC over UDP
To: None <gnats-bugs@gnats.netbsd.org>
From: None <Michael.Eriksson@era-t.ericsson.se>
List: netbsd-bugs
Date: 02/11/1997 12:04:19
>Number:         3207
>Category:       bin
>Synopsis:       showmount(8) uses RPC over UDP
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    bin-bug-people (Utility Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Tue Feb 11 03:20:01 1997
>Last-Modified:
>Originator:     Michael Eriksson
>Organization:
Ericsson Radio Systems AB
>Release:        1.2
>Environment:
NetBSD 1.2

>Description:

showmount(8) uses callrpc(3), which implicitly uses UDP for transport.
Responses can sometimes be too big for a UDP packet (8 kbytes of
encoded data), and the program will fail. Thus, the program should use
TCP for transport instead.

>How-To-Repeat:

% showmount -a nfsserver

>Fix:

*** /usr/src/usr.bin/showmount/showmount.c	Wed May  1 20:14:10 1996
--- showmount.c	Tue Feb 11 10:18:35 1997
***************
*** 113,121 ****
  {
  	struct exportslist *exp;
  	struct grouplist *grp;
! 	int estat, rpcs = 0, mntvers = 1;
  	char *host;
! 	int ch;
  
  	while ((ch = getopt(argc, argv, "ade3")) != -1)
  		switch((char)ch) {
--- 113,126 ----
  {
  	struct exportslist *exp;
  	struct grouplist *grp;
! 	struct sockaddr_in clnt_sin;
! 	struct hostent *hp;
! 	struct timeval timeout;
! 	int rpcs = 0, mntvers = 1;
! 	enum clnt_stat estat;
! 	CLIENT *client;
  	char *host;
! 	int ch, clnt_sock;
  
  	while ((ch = getopt(argc, argv, "ade3")) != -1)
  		switch((char)ch) {
***************
*** 154,175 ****
  	if (rpcs == 0)
  		rpcs = DODUMP;
  
! 	if (rpcs & DODUMP)
! 		if ((estat = callrpc(host, RPCPROG_MNT, mntvers,
! 			RPCMNT_DUMP, xdr_void, (char *)0,
! 			xdr_mntdump, (char *)&mntdump)) != 0) {
  			fprintf(stderr, "showmount: Can't do Mountdump rpc: ");
  			clnt_perrno(estat);
  			exit(1);
  		}
! 	if (rpcs & DOEXPORTS)
! 		if ((estat = callrpc(host, RPCPROG_MNT, mntvers,
! 			RPCMNT_EXPORT, xdr_void, (char *)0,
! 			xdr_exports, (char *)&exports)) != 0) {
  			fprintf(stderr, "showmount: Can't do Exports rpc: ");
  			clnt_perrno(estat);
  			exit(1);
  		}
  
  	/* Now just print out the results */
  	if (rpcs & DODUMP) {
--- 159,200 ----
  	if (rpcs == 0)
  		rpcs = DODUMP;
  
! 	if ((hp = gethostbyname(host)) == NULL) {
! 		fprintf(stderr, "showmount: unknown host %s\n", host);
! 		exit(1);
! 	}
! 	bzero(&clnt_sin, sizeof clnt_sin);
! 	clnt_sin.sin_len = sizeof clnt_sin;
! 	clnt_sin.sin_family = AF_INET;
! 	bcopy(hp->h_addr, (char *)&clnt_sin.sin_addr, hp->h_length);
! 	clnt_sock = RPC_ANYSOCK;
! 	client = clnttcp_create(&clnt_sin, RPCPROG_MNT, mntvers,
! 				&clnt_sock, 0, 0);
! 	if (client == NULL) {
! 		clnt_pcreateerror("showmount: clnttcp_create");
! 		exit(1);
! 	}
! 	timeout.tv_sec = 30;
! 	timeout.tv_usec = 0;
! 
! 	if (rpcs & DODUMP) {
! 		estat = clnt_call(client, RPCMNT_DUMP, xdr_void, (char *)0,
! 				  xdr_mntdump, (char *)&mntdump, timeout);
! 		if (estat != RPC_SUCCESS) {
  			fprintf(stderr, "showmount: Can't do Mountdump rpc: ");
  			clnt_perrno(estat);
  			exit(1);
  		}
! 	}
! 	if (rpcs & DOEXPORTS) {
! 		estat = clnt_call(client, RPCMNT_EXPORT, xdr_void, (char *)0,
! 				  xdr_exports, (char *)&exports, timeout);
! 		if (estat != RPC_SUCCESS) {
  			fprintf(stderr, "showmount: Can't do Exports rpc: ");
  			clnt_perrno(estat);
  			exit(1);
  		}
+ 	}
  
  	/* Now just print out the results */
  	if (rpcs & DODUMP) {

>Audit-Trail:
>Unformatted: