Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 21 Jun 2001 20:48:23 +0100
From:      Ian Dowse <iedowse@maths.tcd.ie>
To:        freebsd-net@freebsd.org
Subject:   Re: Using connect() on UDP RPC client sockets. 
Message-ID:   <200106212048.aa13306@salmon.maths.tcd.ie>
In-Reply-To: Your message of "Sun, 20 May 2001 22:56:34 BST." <200105202256.aa30752@salmon.maths.tcd.ie> 

next in thread | previous in thread | raw e-mail | index | archive | help
In message <200105202256.aa30752@salmon.maths.tcd.ie>, Ian Dowse writes:
>
>I would like to change the RPC client code to use connect() for
>UDP sockets. I think this would be a more modern behaviour; it is

As a first step to achieve this goal, I would like to commit the
following patch to the RPC library in -current. This does not change
the default behaviour, but it allows clients to use connect() on
UDP sockets if desired.

Following this change, it is possible to use clnt_control() to
specify that the client socket should use connect() i.e.:

	int doconnect = 1;

	clp = clnt_create(...);
	clnt_control(clp, CLSET_CONNECT, (char *)&doconnect);
	clnt_call(clp, ...);

The first use of this new feature will be to make mount_nfs do the
right thing when the remote nfsd responds from the wrong address.
Currently mount_nfs cannot detect this problem, so it goes ahead
with the mount(). However since the kernel uses connect(), it does
not see the replies and the mount becomes hung, possibly requiring
a reboot to correct.

Any objections to this approach?

Ian


Index: include/rpc/clnt.h
===================================================================
RCS file: /dump/FreeBSD-CVS/src/include/rpc/clnt.h,v
retrieving revision 1.13
diff -u -r1.13 clnt.h
--- include/rpc/clnt.h	2001/03/27 21:27:33	1.13
+++ include/rpc/clnt.h	2001/06/06 23:43:31
@@ -229,6 +229,7 @@
 #define CLSET_RETRY_TIMEOUT 4   /* set retry timeout (timeval) */
 #define CLGET_RETRY_TIMEOUT 5   /* get retry timeout (timeval) */
 #define CLSET_ASYNC		19
+#define CLSET_CONNECT		20	/* Use connect() for UDP. (int) */
 
 /*
  * void
Index: lib/libc/rpc/clnt_dg.c
===================================================================
RCS file: /dump/FreeBSD-CVS/src/lib/libc/rpc/clnt_dg.c,v
retrieving revision 1.6
diff -u -r1.6 clnt_dg.c
--- lib/libc/rpc/clnt_dg.c	2001/05/18 19:43:18	1.6
+++ lib/libc/rpc/clnt_dg.c	2001/06/21 19:27:09
@@ -126,6 +126,8 @@
 	u_int			cu_recvsz;	/* recv size */
 	struct pollfd		pfdp;
 	int			cu_async;
+	int			cu_connect;	/* Use connect(). */
+	int			cu_connected;	/* Have done connect(). */
 	char			cu_inbuf[1];
 };
 
@@ -239,6 +241,8 @@
 	cu->cu_sendsz = sendsz;
 	cu->cu_recvsz = recvsz;
 	cu->cu_async = FALSE;
+	cu->cu_connect = FALSE;
+	cu->cu_connected = FALSE;
 	(void) gettimeofday(&now, NULL);
 	call_msg.rm_xid = __RPC_GETXID(&now);
 	call_msg.rm_call.cb_prog = program;
@@ -308,9 +312,10 @@
 	struct timeval startime, curtime;
 	int firsttimeout = 1;
 	int dtbsize = __rpc_dtbsize();
+	struct sockaddr *sa;
 	sigset_t mask;
 	sigset_t newmask;
-	socklen_t inlen;
+	socklen_t inlen, salen;
 	ssize_t recvlen = 0;
 	int rpc_lock_value;
 	u_int32_t xid;
@@ -332,6 +337,22 @@
 		timeout = cu->cu_total;	/* use default timeout */
 	}
 
+	if (cu->cu_connect && !cu->cu_connected) {
+		if (_connect(cu->cu_fd, (struct sockaddr *)&cu->cu_raddr,
+		    cu->cu_rlen) < 0) {
+			release_fd_lock(cu->cu_fd, mask);
+			cu->cu_error.re_errno = errno;
+			return (cu->cu_error.re_status = RPC_CANTSEND);
+		}
+		cu->cu_connected = 1;
+	}
+	if (cu->cu_connected) {
+		sa = NULL;
+		salen = 0;
+	} else {
+		sa = (struct sockaddr *)&cu->cu_raddr;
+		salen = cu->cu_rlen;
+	}
 	time_waited.tv_sec = 0;
 	time_waited.tv_usec = 0;
 	retransmit_time = cu->cu_wait;
@@ -360,9 +381,7 @@
 	outlen = (size_t)XDR_GETPOS(xdrs);
 
 send_again:
-	if (_sendto(cu->cu_fd, cu->cu_outbuf, outlen, 0,
-	    (struct sockaddr *)(void *)&cu->cu_raddr, (socklen_t)cu->cu_rlen)
-	    != outlen) {
+	if (_sendto(cu->cu_fd, cu->cu_outbuf, outlen, 0, sa, salen) != outlen) {
 		cu->cu_error.re_errno = errno;
 		release_fd_lock(cu->cu_fd, mask);
 		return (cu->cu_error.re_status = RPC_CANTSEND);
@@ -737,6 +756,9 @@
 		break;
 	case CLSET_ASYNC:
 		cu->cu_async = *(int *)(void *)info;
+		break;
+	case CLSET_CONNECT:
+		cu->cu_connect = *(int *)(void *)info;
 		break;
 	default:
 		release_fd_lock(cu->cu_fd, mask);
Index: lib/libc/rpc/rpc_clnt_create.3
===================================================================
RCS file: /dump/FreeBSD-CVS/src/lib/libc/rpc/rpc_clnt_create.3,v
retrieving revision 1.1
diff -u -r1.1 rpc_clnt_create.3
--- lib/libc/rpc/rpc_clnt_create.3	2001/03/19 12:49:51	1.1
+++ lib/libc/rpc/rpc_clnt_create.3	2001/06/21 19:20:24
@@ -105,6 +105,7 @@
 .Bl -column CLSET_RETRY_TIMEOUT "struct timeval *" "set total timeout"
 .It Dv CLSET_RETRY_TIMEOUT Ta "struct timeval *" Ta "set the retry timeout"
 .It Dv CLGET_RETRY_TIMEOUT Ta "struct timeval *" Ta "get the retry timeout"
+.It Dv CLSET_CONNECT Ta "int *" Ta "use connect()"
 .El
 .Pp
 The retry timeout is the time that RPC

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




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