From owner-freebsd-net Thu Jun 21 12:48:31 2001 Delivered-To: freebsd-net@freebsd.org Received: from salmon.maths.tcd.ie (salmon.maths.tcd.ie [134.226.81.11]) by hub.freebsd.org (Postfix) with SMTP id 79A2037B401 for ; Thu, 21 Jun 2001 12:48:24 -0700 (PDT) (envelope-from iedowse@maths.tcd.ie) Received: from walton.maths.tcd.ie by salmon.maths.tcd.ie with SMTP id ; 21 Jun 2001 20:48:23 +0100 (BST) To: freebsd-net@freebsd.org Subject: Re: Using connect() on UDP RPC client sockets. In-Reply-To: Your message of "Sun, 20 May 2001 22:56:34 BST." <200105202256.aa30752@salmon.maths.tcd.ie> Date: Thu, 21 Jun 2001 20:48:23 +0100 From: Ian Dowse Message-ID: <200106212048.aa13306@salmon.maths.tcd.ie> Sender: owner-freebsd-net@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.org 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