glibc/sunrpc/clnt_udp.c
Roland McGrath b20e47cb14 Tue Mar 19 14:18:42 1996 Roland McGrath <roland@charlie-brown.gnu.ai.mit.edu>
* sysdeps/unix/bsd/pause.c: Moved to sysdeps/unix/common/pause.c.

Mon Mar  4 20:17:28 1996  David Mosberger-Tang  <davidm@azstarnet.com>

	* sysdeps/unix/sysv/linux/adjtime.c: Use INT_MAX instead of LONG_MAX.

	* sysdeps/unix/sysv/Makefile (sysdep_routines): Don't add s_getdents.

	* sysdeps/unix/sysv/linux/Makefile (sysdep_routines): Don't add mount,
	umount.

	* sysdeps/alpha/__math.h (atan, cabs): New functions.

	* sysdeps/unix/sysv/linux/alpha/sigsuspend.S: new file (syscall
 	expects set-value, not pointer to it).

Sun Feb 25 22:36:10 1996  David Mosberger-Tang  <davidm@azstarnet.com>

	* sysdeps/unix/sysv/linux/alpha/profil-counter.h: New file.

	* gmon/gmon.c (__bb_head): new variable.
	(write_hist, write_call_graph, write_bb_counts): new functions.
	(_mcleanup): modified to call above functions instead of directly
 	writing out gmon.out.
	* gmon/sys/gmon.h (struct __bb): New type.
	(struct gmonhdr): Type removed.
	(struct gmonparam): New member `log_hashfraction'.
	(GMONVERSION): Macro removed.

	* gmon/sys/gmon_out.h, gmon/bb_exit_func.c,
 	sysdeps/generic/bb_init_func.c, sysdeps/alpha/bb_init_func.S: new
 	files.
	* gmon/Makefile (headers): Add sys/gmon_out.h.
	(routines): Add bb_init_func, bb_exit_func.

	* gmon/mcount.c: Avoid integer division.

Wed Feb 21 23:56:41 1996  David Mosberger-Tang  <davidm@azstarnet.com>

	* sysdeps/alpha/setjmp.S: switched order in which sp and fp are
 	passed to match what __sigsetjmp_aux() expects.

Tue Feb 20 11:33:46 1996  David Mosberger-Tang  <davidm@azstarnet.com>

	* sysdeps/unix/sysv/linux/alpha/syscalls.list (select, bind,
 	connect, getpeername, getsockname, listen, recv, recvfrom,
 	recvmsg, send, sendmsg, sendto, setsockopt, shutdown, socketpair):
 	added to override same-name assembly file in the parent directory.

	* stdlib/stdlib.h: add include of sys/types.h in front of random
 	etc declarations to ensure int32_t is declared.

	* stdlib/random.c, stdlib/random_r.c: replaced "long int" by int32_t
	where 32 bit integers are required.  Also change LONG_MAX into
	0x7fffffff since the intent is to turn off the sign bit in a
	32 bit integer.

	* time/offtime.c (__offtime): Use Paul Eggert's code to deal
	with very large values for "days" (e.g., 64 bit values).

Mon Feb 19 22:22:12 1996  David Mosberger-Tang  <davidm@azstarnet.com>

	* stdlib/stdlib.h (__random, __random_r, random_r, struct
 	random_data): use int32_t instead of `long int'.

Sat Feb 17 11:29:29 1996  David Mosberger-Tang  <davidm@azstarnet.com>

	* sysdeps/unix/sysv/linux/alpha/ioperm.c: new file.

	* sysdeps/alpha/ffs.S: new file.

	* sysdeps/alpha/fabs.c: File removed.

	* time/tzfile.c (__tzfile_read): counter variable is i, *not*
	num_transitions!

	* time/offtime.c: make capable of dealing with very large (64 bit)
 	time_t values.  Use old algorithm until a year is reached that
	is an integer multiple of 400, then use DAYS_PER_400_YEARS to
	do the remainder in a single division.

	* sysdeps/generic/ffs.c (ffs): fix variable declarations to
	be unsigned int, not unsigned long.

	* string/test-ffs.c (main): add test case with all upper bits
	set.

	* stdlib/tst-strtol.c: add tests cases for machines where
	sizeof(long)==8.

	* stdlib/testrand.c (main): disallow rand() to return negative
 	integers.

	* stdlib/testmb.c (main): fix format to use %lx instead of %x.

	* stdlib/stdlib.h: on 64 bit machines, declare
	struct random_data, __random(),  __random_r, and random_r to
	return "int" instead of "long int".

	* stdlib/random_r.c: 64 bit machines use "int" instead of "long
 	int".  Similarly, use INT_MAX instead of LONG_MAX.

	* stdlib/random.c: on 64 bit machines, randtbl[] and __random[]
 	need to operate on "int" instead of "long int".

	* locale/locfile-hash.c (compute_hashval): make shifted constant
	a long to avoid loosing bits on 64 bit machines.

	* dirent/tst-seekdir.c (main): fix confusing comment; print
	a line to mark point where directory is rewound.

Fri Feb 16 15:01:49 1996  David Mosberger-Tang  <davidm@azstarnet.com>

	* time/strftime.c (strftime): any hour > 11 is PM (not > 12!).

Wed Feb 14 00:21:17 1996  David Mosberger-Tang  <davidm@azstarnet.com>

	* sysdeps/unix/sysv/linux/alpha/Makefile,
	sysdeps/unix/sysv/linux/alpha/brk.S,
	sysdeps/unix/sysv/linux/alpha/fpu_control.c,
	sysdeps/unix/sysv/linux/alpha/fpu_control.h,
	sysdeps/unix/sysv/linux/alpha/ieee_get_fp_control.S,
	sysdeps/unix/sysv/linux/alpha/ieee_set_fp_control.S,
	sysdeps/unix/sysv/linux/alpha/pipe.S,
	sysdeps/unix/sysv/linux/alpha/setfpucw.c,
	sysdeps/unix/sysv/linux/alpha/sigprocmask.c,
	sysdeps/unix/sysv/linux/alpha/speed.c,
	sysdeps/unix/sysv/linux/alpha/start.S,
	sysdeps/unix/sysv/linux/alpha/syscall.S,
	sysdeps/unix/sysv/linux/alpha/syscalls.list,
	sysdeps/unix/sysv/linux/alpha/alpha/regdef.h,
	sysdeps/unix/sysv/linux/alpha/sysdep.S,
	sysdeps/unix/sysv/linux/alpha/sysdep.h: New files.

	* sysdeps/alpha/setjmp_aux.c (__sigsetjmp_aux): restore return
 	address register before returning (gcc 2.7.1 doesn't do it,
 	presumably because $26 is declared as a global variable).

	* sysdeps/unix/sysv/linux/sys/mman.h: msync was missing "flags"
	argument.

	* sysdeps/unix/alarm.c (alarm): do roundup using test & increment
	instead of multiplication.

	* sysdeps/posix/sleep.c (sleep): initialize sa_mask to mask of
	currently blocked signals instead of the empty mask to ensure
	that execution of alarm handler occurs with none of the currently
	blocked signals enabled.

	* sysdeps/unix/alpha/sysdep.h: new file (adapted from OSF/1 version).

	* sysdeps/unix/bsd/osf/alpha/sysdep.h: include
 	sysdeps/unix/alpha/sysdep.h and removed definitions now in that file.

	* sysdeps/alpha/divrem.S, sysdeps/alpha/htonl.S,
	sysdeps/alpha/htons.S, sysdeps/alpha/machine-gmon.h,
	sysdeps/alpha/_mcount.S, sysdeps/alpha/ntohl.s, sysdeps/alpha/ntohs.s,
	sysdeps/alpha/strlen.S: New files.

	* sysdeps/alpha/divl.S, sysdeps/alpha/divlu.S, sysdeps/alpha/divq.S,
	sysdeps/alpha/divqu.S, sysdeps/alpha/divrem.m4,
	sysdeps/alpha/macros.m4, sysdeps/alpha/reml.S, sysdeps/alpha/remlu.S,
	sysdeps/alpha/remq.S, sysdeps/alpha/remqu.S, sysdeps/alpha/strlen.c:
 	Removed.

	* sysdeps/generic/sbrk.c (__sbrk): argument is of type ptrdiff_t, not
	int.

	* sysdeps/alpha/__longjmp.c (__longjmp): moved dummy while loop
	to end of function to avoid a jump across NOPs.

	* sysdeps/alpha/Makefile (sysdep_routines): Removed all rules
 	pertaining to integer division/remainder routines since new code
 	doesn't require them.

	* sunrpc/xdr_mem.c, sunrpc/xdr_stdio.c: Use 4 instead of sizeof(long)
	where 32 bit quantities are consumed/stored.  Various other minor
	64-bit cleanups (casting).

	* sunrpc/xdr.c (xdr_int): test for sizeof(int)==4 to determine
 	whether xdr_long or xdr_short should be used to encode an int.
  	Notice that an xdr_long is 4 bytes independent of the architecture
	(otherwise no Alpha could interoperate with existing NFS servers,
 	for example).  Ditto for enums.

	* sunrpc/svc_udp.c (svcudp_recv): changed test from 4*sizeof(u_long)
	to 16 since it really wants 16 bytes.

	* sunrpc/svc.c (maskp): changed from u_long* to u_int32*.

	* sunrpc/rpc_cmsg.c (xdr_callmsg), sunrpc/svc_authux.c: increment
	"buf" pointer by casting it to a char* first since a long* may be 8
 	bytes or more and oa->oa_length may be any multiple of 4.

	* sunrpc/rpc/xdr.h (IXDR_GET_LONG, IXDR_PUT_LONG): change casts to
 	u_int32_t (instead of u_long).

	* sunrpc/clnt_udp.c (clntudp_call): replaced sizeof(u_long) by 4
	since it really is testing for 32 bits.  Fixed casts to use
	u_int32 instead of u_long.
	* sunrpc/xdr_rec.c: Likewise.

	* sunrpc/clnt_tcp.c (clnttcp_call): replaced u_long by u_int32.
	* sunrpc/rpc/auth.h: Likewise.

	* limits.h (LONG_MAX, LONG_MIN, ULONG_MAX): use 64 bit values
	for Alpha.

Tue Mar 19 13:27:49 1996  Roland McGrath  <roland@charlie-brown.gnu.ai.mit.edu>

	* sysdeps/i386/fpu/__math.h: New file.
	Contributed by John C. Bowman <bowman@hagar.ph.utexas.edu>.

Sun Mar 17 00:28:16 1996  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

	* sysdeps/posix/clock.c: Don't multiply the return value by
	CLOCKS_PER_SEC or CLK_TCK.

	* sysdeps/mach/hurd/getcwd.c: Fail with ENOENT if a parent directory
	scan finds no match.

	* posix/unistd.h (setpgrp): Declare no-arg version unless __FAVOR_BSD.
	* misc/bsd-compat.c (setpgrp): New function, two arg version.
	* sysdeps/stub/setpgid.c: Remove setpgrp alias.
	* sysdeps/mach/hurd/setpgid.c: Likewise.
	* sysdeps/unix/sysv/sysv4/setpgid.c: Likewise.
	* sysdeps/unix/common/syscalls.list (setpgid): Remove setpgrp alias.
	* sysdeps/unix/sysv/irix4/syscalls.list: Likewise.
	* sysdeps/unix/sysv/linux/setpgrp.c: Obsolete file removed.
	* posix/setpgrp.c (setpgrp): New file.
	* posix/Makefile (routines): Add setpgrp.

Tue Feb  6 12:46:29 1996  David Mosberger-Tang  <davidm@azstarnet.com>

	* libc-symbols.h (weak_alias, weak_symbol): added definitions
	for ECOFF (HAVE_ECOFF).
1996-03-19 20:21:54 +00:00

443 lines
12 KiB
C

/* @(#)clnt_udp.c 2.2 88/08/01 4.0 RPCSRC */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#if !defined(lint) && defined(SCCSIDS)
static char sccsid[] = "@(#)clnt_udp.c 1.39 87/08/11 Copyr 1984 Sun Micro";
#endif
/*
* clnt_udp.c, Implements a UDP/IP based, client side RPC.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
#include <stdio.h>
#include <rpc/rpc.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netdb.h>
#include <errno.h>
#include <rpc/pmap_clnt.h>
extern int errno;
/*
* UDP bases client side rpc operations
*/
static enum clnt_stat clntudp_call();
static void clntudp_abort();
static void clntudp_geterr();
static bool_t clntudp_freeres();
static bool_t clntudp_control();
static void clntudp_destroy();
static struct clnt_ops udp_ops = {
clntudp_call,
clntudp_abort,
clntudp_geterr,
clntudp_freeres,
clntudp_destroy,
clntudp_control
};
/*
* Private data kept per client handle
*/
struct cu_data {
int cu_sock;
bool_t cu_closeit;
struct sockaddr_in cu_raddr;
int cu_rlen;
struct timeval cu_wait;
struct timeval cu_total;
struct rpc_err cu_error;
XDR cu_outxdrs;
u_int cu_xdrpos;
u_int cu_sendsz;
char *cu_outbuf;
u_int cu_recvsz;
char cu_inbuf[1];
};
/*
* Create a UDP based client handle.
* If *sockp<0, *sockp is set to a newly created UPD socket.
* If raddr->sin_port is 0 a binder on the remote machine
* is consulted for the correct port number.
* NB: It is the clients responsibility to close *sockp.
* NB: The rpch->cl_auth is initialized to null authentication.
* Caller may wish to set this something more useful.
*
* wait is the amount of time used between retransmitting a call if
* no response has been heard; retransmition occurs until the actual
* rpc call times out.
*
* sendsz and recvsz are the maximum allowable packet sizes that can be
* sent and received.
*/
CLIENT *
clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz)
struct sockaddr_in *raddr;
u_long program;
u_long version;
struct timeval wait;
register int *sockp;
u_int sendsz;
u_int recvsz;
{
CLIENT *cl;
register struct cu_data *cu;
struct timeval now;
struct rpc_msg call_msg;
cl = (CLIENT *)mem_alloc(sizeof(CLIENT));
if (cl == NULL) {
(void) fprintf(stderr, "clntudp_create: out of memory\n");
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
rpc_createerr.cf_error.re_errno = errno;
goto fooy;
}
sendsz = ((sendsz + 3) / 4) * 4;
recvsz = ((recvsz + 3) / 4) * 4;
cu = (struct cu_data *)mem_alloc(sizeof(*cu) + sendsz + recvsz);
if (cu == NULL) {
(void) fprintf(stderr, "clntudp_create: out of memory\n");
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
rpc_createerr.cf_error.re_errno = errno;
goto fooy;
}
cu->cu_outbuf = &cu->cu_inbuf[recvsz];
(void)gettimeofday(&now, (struct timezone *)0);
if (raddr->sin_port == 0) {
u_short port;
if ((port =
pmap_getport(raddr, program, version, IPPROTO_UDP)) == 0) {
goto fooy;
}
raddr->sin_port = htons(port);
}
cl->cl_ops = &udp_ops;
cl->cl_private = (caddr_t)cu;
cu->cu_raddr = *raddr;
cu->cu_rlen = sizeof (cu->cu_raddr);
cu->cu_wait = wait;
cu->cu_total.tv_sec = -1;
cu->cu_total.tv_usec = -1;
cu->cu_sendsz = sendsz;
cu->cu_recvsz = recvsz;
call_msg.rm_xid = getpid() ^ now.tv_sec ^ now.tv_usec;
call_msg.rm_direction = CALL;
call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
call_msg.rm_call.cb_prog = program;
call_msg.rm_call.cb_vers = version;
xdrmem_create(&(cu->cu_outxdrs), cu->cu_outbuf,
sendsz, XDR_ENCODE);
if (! xdr_callhdr(&(cu->cu_outxdrs), &call_msg)) {
goto fooy;
}
cu->cu_xdrpos = XDR_GETPOS(&(cu->cu_outxdrs));
if (*sockp < 0) {
int dontblock = 1;
*sockp = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (*sockp < 0) {
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
rpc_createerr.cf_error.re_errno = errno;
goto fooy;
}
/* attempt to bind to prov port */
(void)bindresvport(*sockp, (struct sockaddr_in *)0);
/* the sockets rpc controls are non-blocking */
(void)ioctl(*sockp, FIONBIO, (char *) &dontblock);
cu->cu_closeit = TRUE;
} else {
cu->cu_closeit = FALSE;
}
cu->cu_sock = *sockp;
cl->cl_auth = authnone_create();
return (cl);
fooy:
if (cu)
mem_free((caddr_t)cu, sizeof(*cu) + sendsz + recvsz);
if (cl)
mem_free((caddr_t)cl, sizeof(CLIENT));
return ((CLIENT *)NULL);
}
CLIENT *
clntudp_create(raddr, program, version, wait, sockp)
struct sockaddr_in *raddr;
u_long program;
u_long version;
struct timeval wait;
register int *sockp;
{
return(clntudp_bufcreate(raddr, program, version, wait, sockp,
UDPMSGSIZE, UDPMSGSIZE));
}
static enum clnt_stat
clntudp_call(cl, proc, xargs, argsp, xresults, resultsp, utimeout)
register CLIENT *cl; /* client handle */
u_long proc; /* procedure number */
xdrproc_t xargs; /* xdr routine for args */
caddr_t argsp; /* pointer to args */
xdrproc_t xresults; /* xdr routine for results */
caddr_t resultsp; /* pointer to results */
struct timeval utimeout; /* seconds to wait before giving up */
{
register struct cu_data *cu = (struct cu_data *)cl->cl_private;
register XDR *xdrs;
register int outlen;
register int inlen;
int fromlen;
#ifdef FD_SETSIZE
fd_set readfds;
fd_set mask;
#else
int readfds;
register int mask;
#endif /* def FD_SETSIZE */
struct sockaddr_in from;
struct rpc_msg reply_msg;
XDR reply_xdrs;
struct timeval time_waited;
bool_t ok;
int nrefreshes = 2; /* number of times to refresh cred */
struct timeval timeout;
if (cu->cu_total.tv_usec == -1) {
timeout = utimeout; /* use supplied timeout */
} else {
timeout = cu->cu_total; /* use default timeout */
}
time_waited.tv_sec = 0;
time_waited.tv_usec = 0;
call_again:
xdrs = &(cu->cu_outxdrs);
xdrs->x_op = XDR_ENCODE;
XDR_SETPOS(xdrs, cu->cu_xdrpos);
/*
* the transaction is the first thing in the out buffer
*/
(*(u_short *)(cu->cu_outbuf))++;
if ((! XDR_PUTLONG(xdrs, (long *)&proc)) ||
(! AUTH_MARSHALL(cl->cl_auth, xdrs)) ||
(! (*xargs)(xdrs, argsp)))
return (cu->cu_error.re_status = RPC_CANTENCODEARGS);
outlen = (int)XDR_GETPOS(xdrs);
send_again:
if (sendto(cu->cu_sock, cu->cu_outbuf, outlen, 0,
(struct sockaddr *)&(cu->cu_raddr), cu->cu_rlen)
!= outlen) {
cu->cu_error.re_errno = errno;
return (cu->cu_error.re_status = RPC_CANTSEND);
}
/*
* Hack to provide rpc-based message passing
*/
if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
return (cu->cu_error.re_status = RPC_TIMEDOUT);
}
/*
* sub-optimal code appears here because we have
* some clock time to spare while the packets are in flight.
* (We assume that this is actually only executed once.)
*/
reply_msg.acpted_rply.ar_verf = _null_auth;
reply_msg.acpted_rply.ar_results.where = resultsp;
reply_msg.acpted_rply.ar_results.proc = xresults;
#ifdef FD_SETSIZE
FD_ZERO(&mask);
FD_SET(cu->cu_sock, &mask);
#else
mask = 1 << cu->cu_sock;
#endif /* def FD_SETSIZE */
for (;;) {
readfds = mask;
switch (select(_rpc_dtablesize(), &readfds, (int *)NULL,
(int *)NULL, &(cu->cu_wait))) {
case 0:
time_waited.tv_sec += cu->cu_wait.tv_sec;
time_waited.tv_usec += cu->cu_wait.tv_usec;
while (time_waited.tv_usec >= 1000000) {
time_waited.tv_sec++;
time_waited.tv_usec -= 1000000;
}
if ((time_waited.tv_sec < timeout.tv_sec) ||
((time_waited.tv_sec == timeout.tv_sec) &&
(time_waited.tv_usec < timeout.tv_usec)))
goto send_again;
return (cu->cu_error.re_status = RPC_TIMEDOUT);
/*
* buggy in other cases because time_waited is not being
* updated.
*/
case -1:
if (errno == EINTR)
continue;
cu->cu_error.re_errno = errno;
return (cu->cu_error.re_status = RPC_CANTRECV);
}
do {
fromlen = sizeof(struct sockaddr);
inlen = recvfrom(cu->cu_sock, cu->cu_inbuf,
(int) cu->cu_recvsz, 0,
(struct sockaddr *)&from, &fromlen);
} while (inlen < 0 && errno == EINTR);
if (inlen < 0) {
if (errno == EWOULDBLOCK)
continue;
cu->cu_error.re_errno = errno;
return (cu->cu_error.re_status = RPC_CANTRECV);
}
if (inlen < 4)
continue;
/* see if reply transaction id matches sent id */
if (*((u_int32_t *)(cu->cu_inbuf)) != *((u_int32_t *)(cu->cu_outbuf)))
continue;
/* we now assume we have the proper reply */
break;
}
/*
* now decode and validate the response
*/
xdrmem_create(&reply_xdrs, cu->cu_inbuf, (u_int)inlen, XDR_DECODE);
ok = xdr_replymsg(&reply_xdrs, &reply_msg);
/* XDR_DESTROY(&reply_xdrs); save a few cycles on noop destroy */
if (ok) {
_seterr_reply(&reply_msg, &(cu->cu_error));
if (cu->cu_error.re_status == RPC_SUCCESS) {
if (! AUTH_VALIDATE(cl->cl_auth,
&reply_msg.acpted_rply.ar_verf)) {
cu->cu_error.re_status = RPC_AUTHERROR;
cu->cu_error.re_why = AUTH_INVALIDRESP;
}
if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) {
xdrs->x_op = XDR_FREE;
(void)xdr_opaque_auth(xdrs,
&(reply_msg.acpted_rply.ar_verf));
}
} /* end successful completion */
else {
/* maybe our credentials need to be refreshed ... */
if (nrefreshes > 0 && AUTH_REFRESH(cl->cl_auth)) {
nrefreshes--;
goto call_again;
}
} /* end of unsuccessful completion */
} /* end of valid reply message */
else {
cu->cu_error.re_status = RPC_CANTDECODERES;
}
return (cu->cu_error.re_status);
}
static void
clntudp_geterr(cl, errp)
CLIENT *cl;
struct rpc_err *errp;
{
register struct cu_data *cu = (struct cu_data *)cl->cl_private;
*errp = cu->cu_error;
}
static bool_t
clntudp_freeres(cl, xdr_res, res_ptr)
CLIENT *cl;
xdrproc_t xdr_res;
caddr_t res_ptr;
{
register struct cu_data *cu = (struct cu_data *)cl->cl_private;
register XDR *xdrs = &(cu->cu_outxdrs);
xdrs->x_op = XDR_FREE;
return ((*xdr_res)(xdrs, res_ptr));
}
static void
clntudp_abort(/*h*/)
/*CLIENT *h;*/
{
}
static bool_t
clntudp_control(cl, request, info)
CLIENT *cl;
int request;
char *info;
{
register struct cu_data *cu = (struct cu_data *)cl->cl_private;
switch (request) {
case CLSET_TIMEOUT:
cu->cu_total = *(struct timeval *)info;
break;
case CLGET_TIMEOUT:
*(struct timeval *)info = cu->cu_total;
break;
case CLSET_RETRY_TIMEOUT:
cu->cu_wait = *(struct timeval *)info;
break;
case CLGET_RETRY_TIMEOUT:
*(struct timeval *)info = cu->cu_wait;
break;
case CLGET_SERVER_ADDR:
*(struct sockaddr_in *)info = cu->cu_raddr;
break;
default:
return (FALSE);
}
return (TRUE);
}
static void
clntudp_destroy(cl)
CLIENT *cl;
{
register struct cu_data *cu = (struct cu_data *)cl->cl_private;
if (cu->cu_closeit) {
(void)close(cu->cu_sock);
}
XDR_DESTROY(&(cu->cu_outxdrs));
mem_free((caddr_t)cu, (sizeof(*cu) + cu->cu_sendsz + cu->cu_recvsz));
mem_free((caddr_t)cl, sizeof(CLIENT));
}