Home | History | Annotate | Line # | Download | only in rpc
pmap_rmt.c revision 1.4
      1  1.4      cgd /*	$NetBSD: pmap_rmt.c,v 1.4 1995/02/25 03:01:52 cgd Exp $	*/
      2  1.4      cgd 
      3  1.1      cgd /*
      4  1.1      cgd  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
      5  1.1      cgd  * unrestricted use provided that this legend is included on all tape
      6  1.1      cgd  * media and as a part of the software program in whole or part.  Users
      7  1.1      cgd  * may copy or modify Sun RPC without charge, but are not authorized
      8  1.1      cgd  * to license or distribute it to anyone else except as part of a product or
      9  1.1      cgd  * program developed by the user.
     10  1.1      cgd  *
     11  1.1      cgd  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
     12  1.1      cgd  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
     13  1.1      cgd  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
     14  1.1      cgd  *
     15  1.1      cgd  * Sun RPC is provided with no support and without any obligation on the
     16  1.1      cgd  * part of Sun Microsystems, Inc. to assist in its use, correction,
     17  1.1      cgd  * modification or enhancement.
     18  1.1      cgd  *
     19  1.1      cgd  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
     20  1.1      cgd  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
     21  1.1      cgd  * OR ANY PART THEREOF.
     22  1.1      cgd  *
     23  1.1      cgd  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
     24  1.1      cgd  * or profits or other special, indirect and consequential damages, even if
     25  1.1      cgd  * Sun has been advised of the possibility of such damages.
     26  1.1      cgd  *
     27  1.1      cgd  * Sun Microsystems, Inc.
     28  1.1      cgd  * 2550 Garcia Avenue
     29  1.1      cgd  * Mountain View, California  94043
     30  1.1      cgd  */
     31  1.1      cgd 
     32  1.1      cgd #if defined(LIBC_SCCS) && !defined(lint)
     33  1.1      cgd /*static char *sccsid = "from: @(#)pmap_rmt.c 1.21 87/08/27 Copyr 1984 Sun Micro";*/
     34  1.1      cgd /*static char *sccsid = "from: @(#)pmap_rmt.c	2.2 88/08/01 4.0 RPCSRC";*/
     35  1.4      cgd static char *rcsid = "$NetBSD: pmap_rmt.c,v 1.4 1995/02/25 03:01:52 cgd Exp $";
     36  1.1      cgd #endif
     37  1.1      cgd 
     38  1.1      cgd /*
     39  1.1      cgd  * pmap_rmt.c
     40  1.1      cgd  * Client interface to pmap rpc service.
     41  1.1      cgd  * remote call and broadcast service
     42  1.1      cgd  *
     43  1.1      cgd  * Copyright (C) 1984, Sun Microsystems, Inc.
     44  1.1      cgd  */
     45  1.1      cgd 
     46  1.1      cgd #include <rpc/rpc.h>
     47  1.1      cgd #include <rpc/pmap_prot.h>
     48  1.1      cgd #include <rpc/pmap_clnt.h>
     49  1.1      cgd #include <rpc/pmap_rmt.h>
     50  1.1      cgd #include <sys/socket.h>
     51  1.1      cgd #include <stdio.h>
     52  1.1      cgd #include <errno.h>
     53  1.1      cgd #include <net/if.h>
     54  1.1      cgd #include <sys/ioctl.h>
     55  1.1      cgd #include <arpa/inet.h>
     56  1.1      cgd #define MAX_BROADCAST_SIZE 1400
     57  1.1      cgd 
     58  1.1      cgd static struct timeval timeout = { 3, 0 };
     59  1.1      cgd 
     60  1.1      cgd 
     61  1.1      cgd /*
     62  1.1      cgd  * pmapper remote-call-service interface.
     63  1.1      cgd  * This routine is used to call the pmapper remote call service
     64  1.1      cgd  * which will look up a service program in the port maps, and then
     65  1.1      cgd  * remotely call that routine with the given parameters.  This allows
     66  1.1      cgd  * programs to do a lookup and call in one step.
     67  1.1      cgd */
     68  1.1      cgd enum clnt_stat
     69  1.1      cgd pmap_rmtcall(addr, prog, vers, proc, xdrargs, argsp, xdrres, resp, tout, port_ptr)
     70  1.1      cgd 	struct sockaddr_in *addr;
     71  1.1      cgd 	u_long prog, vers, proc;
     72  1.1      cgd 	xdrproc_t xdrargs, xdrres;
     73  1.1      cgd 	caddr_t argsp, resp;
     74  1.1      cgd 	struct timeval tout;
     75  1.1      cgd 	u_long *port_ptr;
     76  1.1      cgd {
     77  1.1      cgd 	int socket = -1;
     78  1.1      cgd 	register CLIENT *client;
     79  1.1      cgd 	struct rmtcallargs a;
     80  1.1      cgd 	struct rmtcallres r;
     81  1.1      cgd 	enum clnt_stat stat;
     82  1.1      cgd 
     83  1.1      cgd 	addr->sin_port = htons(PMAPPORT);
     84  1.1      cgd 	client = clntudp_create(addr, PMAPPROG, PMAPVERS, timeout, &socket);
     85  1.1      cgd 	if (client != (CLIENT *)NULL) {
     86  1.1      cgd 		a.prog = prog;
     87  1.1      cgd 		a.vers = vers;
     88  1.1      cgd 		a.proc = proc;
     89  1.1      cgd 		a.args_ptr = argsp;
     90  1.1      cgd 		a.xdr_args = xdrargs;
     91  1.1      cgd 		r.port_ptr = port_ptr;
     92  1.1      cgd 		r.results_ptr = resp;
     93  1.1      cgd 		r.xdr_results = xdrres;
     94  1.1      cgd 		stat = CLNT_CALL(client, PMAPPROC_CALLIT, xdr_rmtcall_args, &a,
     95  1.1      cgd 		    xdr_rmtcallres, &r, tout);
     96  1.1      cgd 		CLNT_DESTROY(client);
     97  1.1      cgd 	} else {
     98  1.1      cgd 		stat = RPC_FAILED;
     99  1.1      cgd 	}
    100  1.1      cgd 	(void)close(socket);
    101  1.1      cgd 	addr->sin_port = 0;
    102  1.1      cgd 	return (stat);
    103  1.1      cgd }
    104  1.1      cgd 
    105  1.1      cgd 
    106  1.1      cgd /*
    107  1.1      cgd  * XDR remote call arguments
    108  1.1      cgd  * written for XDR_ENCODE direction only
    109  1.1      cgd  */
    110  1.1      cgd bool_t
    111  1.1      cgd xdr_rmtcall_args(xdrs, cap)
    112  1.1      cgd 	register XDR *xdrs;
    113  1.1      cgd 	register struct rmtcallargs *cap;
    114  1.1      cgd {
    115  1.1      cgd 	u_int lenposition, argposition, position;
    116  1.1      cgd 
    117  1.1      cgd 	if (xdr_u_long(xdrs, &(cap->prog)) &&
    118  1.1      cgd 	    xdr_u_long(xdrs, &(cap->vers)) &&
    119  1.1      cgd 	    xdr_u_long(xdrs, &(cap->proc))) {
    120  1.1      cgd 		lenposition = XDR_GETPOS(xdrs);
    121  1.1      cgd 		if (! xdr_u_long(xdrs, &(cap->arglen)))
    122  1.1      cgd 		    return (FALSE);
    123  1.1      cgd 		argposition = XDR_GETPOS(xdrs);
    124  1.1      cgd 		if (! (*(cap->xdr_args))(xdrs, cap->args_ptr))
    125  1.1      cgd 		    return (FALSE);
    126  1.1      cgd 		position = XDR_GETPOS(xdrs);
    127  1.1      cgd 		cap->arglen = (u_long)position - (u_long)argposition;
    128  1.1      cgd 		XDR_SETPOS(xdrs, lenposition);
    129  1.1      cgd 		if (! xdr_u_long(xdrs, &(cap->arglen)))
    130  1.1      cgd 		    return (FALSE);
    131  1.1      cgd 		XDR_SETPOS(xdrs, position);
    132  1.1      cgd 		return (TRUE);
    133  1.1      cgd 	}
    134  1.1      cgd 	return (FALSE);
    135  1.1      cgd }
    136  1.1      cgd 
    137  1.1      cgd /*
    138  1.1      cgd  * XDR remote call results
    139  1.1      cgd  * written for XDR_DECODE direction only
    140  1.1      cgd  */
    141  1.1      cgd bool_t
    142  1.1      cgd xdr_rmtcallres(xdrs, crp)
    143  1.1      cgd 	register XDR *xdrs;
    144  1.1      cgd 	register struct rmtcallres *crp;
    145  1.1      cgd {
    146  1.1      cgd 	caddr_t port_ptr;
    147  1.1      cgd 
    148  1.1      cgd 	port_ptr = (caddr_t)crp->port_ptr;
    149  1.1      cgd 	if (xdr_reference(xdrs, &port_ptr, sizeof (u_long),
    150  1.1      cgd 	    xdr_u_long) && xdr_u_long(xdrs, &crp->resultslen)) {
    151  1.1      cgd 		crp->port_ptr = (u_long *)port_ptr;
    152  1.1      cgd 		return ((*(crp->xdr_results))(xdrs, crp->results_ptr));
    153  1.1      cgd 	}
    154  1.1      cgd 	return (FALSE);
    155  1.1      cgd }
    156  1.1      cgd 
    157  1.1      cgd 
    158  1.1      cgd /*
    159  1.1      cgd  * The following is kludged-up support for simple rpc broadcasts.
    160  1.1      cgd  * Someday a large, complicated system will replace these trivial
    161  1.1      cgd  * routines which only support udp/ip .
    162  1.1      cgd  */
    163  1.1      cgd 
    164  1.1      cgd static int
    165  1.1      cgd getbroadcastnets(addrs, sock, buf)
    166  1.1      cgd 	struct in_addr *addrs;
    167  1.1      cgd 	int sock;  /* any valid socket will do */
    168  1.1      cgd 	char *buf;  /* why allocxate more when we can use existing... */
    169  1.1      cgd {
    170  1.1      cgd 	struct ifconf ifc;
    171  1.1      cgd         struct ifreq ifreq, *ifr;
    172  1.1      cgd 	struct sockaddr_in *sin;
    173  1.1      cgd         char *cp, *cplim;
    174  1.1      cgd         int n, i = 0;
    175  1.1      cgd 
    176  1.1      cgd         ifc.ifc_len = UDPMSGSIZE;
    177  1.1      cgd         ifc.ifc_buf = buf;
    178  1.1      cgd         if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
    179  1.1      cgd                 perror("broadcast: ioctl (get interface configuration)");
    180  1.1      cgd                 return (0);
    181  1.1      cgd         }
    182  1.1      cgd #define max(a, b) (a > b ? a : b)
    183  1.1      cgd #define size(p)	max((p).sa_len, sizeof(p))
    184  1.1      cgd 	cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */
    185  1.1      cgd 	for (cp = buf; cp < cplim;
    186  1.1      cgd 			cp += sizeof (ifr->ifr_name) + size(ifr->ifr_addr)) {
    187  1.1      cgd 		ifr = (struct ifreq *)cp;
    188  1.1      cgd 		if (ifr->ifr_addr.sa_family != AF_INET)
    189  1.1      cgd 			continue;
    190  1.1      cgd 		ifreq = *ifr;
    191  1.1      cgd                 if (ioctl(sock, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
    192  1.1      cgd                         perror("broadcast: ioctl (get interface flags)");
    193  1.1      cgd                         continue;
    194  1.1      cgd                 }
    195  1.1      cgd                 if ((ifreq.ifr_flags & IFF_BROADCAST) &&
    196  1.1      cgd 		    (ifreq.ifr_flags & IFF_UP)) {
    197  1.1      cgd 			sin = (struct sockaddr_in *)&ifr->ifr_addr;
    198  1.1      cgd #ifdef SIOCGIFBRDADDR   /* 4.3BSD */
    199  1.1      cgd 			if (ioctl(sock, SIOCGIFBRDADDR, (char *)&ifreq) < 0) {
    200  1.1      cgd 				addrs[i++] =
    201  1.1      cgd 				    inet_makeaddr(inet_netof(sin->sin_addr),
    202  1.1      cgd 				    INADDR_ANY);
    203  1.1      cgd 			} else {
    204  1.1      cgd 				addrs[i++] = ((struct sockaddr_in*)
    205  1.1      cgd 				  &ifreq.ifr_addr)->sin_addr;
    206  1.1      cgd 			}
    207  1.1      cgd #else /* 4.2 BSD */
    208  1.1      cgd 			addrs[i++] = inet_makeaddr(inet_netof(sin->sin_addr),
    209  1.1      cgd 			    INADDR_ANY);
    210  1.1      cgd #endif
    211  1.1      cgd 		}
    212  1.1      cgd 	}
    213  1.1      cgd 	return (i);
    214  1.1      cgd }
    215  1.1      cgd 
    216  1.1      cgd typedef bool_t (*resultproc_t)();
    217  1.1      cgd 
    218  1.1      cgd enum clnt_stat
    219  1.1      cgd clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult)
    220  1.1      cgd 	u_long		prog;		/* program number */
    221  1.1      cgd 	u_long		vers;		/* version number */
    222  1.1      cgd 	u_long		proc;		/* procedure number */
    223  1.1      cgd 	xdrproc_t	xargs;		/* xdr routine for args */
    224  1.1      cgd 	caddr_t		argsp;		/* pointer to args */
    225  1.1      cgd 	xdrproc_t	xresults;	/* xdr routine for results */
    226  1.1      cgd 	caddr_t		resultsp;	/* pointer to results */
    227  1.1      cgd 	resultproc_t	eachresult;	/* call with each result obtained */
    228  1.1      cgd {
    229  1.1      cgd 	enum clnt_stat stat;
    230  1.1      cgd 	AUTH *unix_auth = authunix_create_default();
    231  1.1      cgd 	XDR xdr_stream;
    232  1.1      cgd 	register XDR *xdrs = &xdr_stream;
    233  1.1      cgd 	int outlen, inlen, fromlen, nets;
    234  1.1      cgd 	register int sock;
    235  1.1      cgd 	int on = 1;
    236  1.1      cgd 	fd_set mask;
    237  1.1      cgd 	fd_set readfds;
    238  1.1      cgd 	register int i;
    239  1.1      cgd 	bool_t done = FALSE;
    240  1.1      cgd 	register u_long xid;
    241  1.1      cgd 	u_long port;
    242  1.1      cgd 	struct in_addr addrs[20];
    243  1.1      cgd 	struct sockaddr_in baddr, raddr; /* broadcast and response addresses */
    244  1.1      cgd 	struct rmtcallargs a;
    245  1.1      cgd 	struct rmtcallres r;
    246  1.1      cgd 	struct rpc_msg msg;
    247  1.1      cgd 	struct timeval t;
    248  1.1      cgd 	char outbuf[MAX_BROADCAST_SIZE], inbuf[UDPMSGSIZE];
    249  1.1      cgd 
    250  1.1      cgd 	/*
    251  1.1      cgd 	 * initialization: create a socket, a broadcast address, and
    252  1.1      cgd 	 * preserialize the arguments into a send buffer.
    253  1.1      cgd 	 */
    254  1.1      cgd 	if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
    255  1.1      cgd 		perror("Cannot create socket for broadcast rpc");
    256  1.1      cgd 		stat = RPC_CANTSEND;
    257  1.1      cgd 		goto done_broad;
    258  1.1      cgd 	}
    259  1.1      cgd #ifdef SO_BROADCAST
    260  1.1      cgd 	if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) {
    261  1.1      cgd 		perror("Cannot set socket option SO_BROADCAST");
    262  1.1      cgd 		stat = RPC_CANTSEND;
    263  1.1      cgd 		goto done_broad;
    264  1.1      cgd 	}
    265  1.1      cgd #endif /* def SO_BROADCAST */
    266  1.1      cgd 	FD_ZERO(&mask);
    267  1.1      cgd 	FD_SET(sock, &mask);
    268  1.1      cgd 	nets = getbroadcastnets(addrs, sock, inbuf);
    269  1.1      cgd 	bzero((char *)&baddr, sizeof (baddr));
    270  1.1      cgd 	baddr.sin_family = AF_INET;
    271  1.1      cgd 	baddr.sin_port = htons(PMAPPORT);
    272  1.1      cgd 	baddr.sin_addr.s_addr = htonl(INADDR_ANY);
    273  1.1      cgd /*	baddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); */
    274  1.1      cgd 	(void)gettimeofday(&t, (struct timezone *)0);
    275  1.1      cgd 	msg.rm_xid = xid = getpid() ^ t.tv_sec ^ t.tv_usec;
    276  1.1      cgd 	t.tv_usec = 0;
    277  1.1      cgd 	msg.rm_direction = CALL;
    278  1.1      cgd 	msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
    279  1.1      cgd 	msg.rm_call.cb_prog = PMAPPROG;
    280  1.1      cgd 	msg.rm_call.cb_vers = PMAPVERS;
    281  1.1      cgd 	msg.rm_call.cb_proc = PMAPPROC_CALLIT;
    282  1.1      cgd 	msg.rm_call.cb_cred = unix_auth->ah_cred;
    283  1.1      cgd 	msg.rm_call.cb_verf = unix_auth->ah_verf;
    284  1.1      cgd 	a.prog = prog;
    285  1.1      cgd 	a.vers = vers;
    286  1.1      cgd 	a.proc = proc;
    287  1.1      cgd 	a.xdr_args = xargs;
    288  1.1      cgd 	a.args_ptr = argsp;
    289  1.1      cgd 	r.port_ptr = &port;
    290  1.1      cgd 	r.xdr_results = xresults;
    291  1.1      cgd 	r.results_ptr = resultsp;
    292  1.1      cgd 	xdrmem_create(xdrs, outbuf, MAX_BROADCAST_SIZE, XDR_ENCODE);
    293  1.1      cgd 	if ((! xdr_callmsg(xdrs, &msg)) || (! xdr_rmtcall_args(xdrs, &a))) {
    294  1.1      cgd 		stat = RPC_CANTENCODEARGS;
    295  1.1      cgd 		goto done_broad;
    296  1.1      cgd 	}
    297  1.1      cgd 	outlen = (int)xdr_getpos(xdrs);
    298  1.1      cgd 	xdr_destroy(xdrs);
    299  1.1      cgd 	/*
    300  1.1      cgd 	 * Basic loop: broadcast a packet and wait a while for response(s).
    301  1.1      cgd 	 * The response timeout grows larger per iteration.
    302  1.1      cgd 	 */
    303  1.1      cgd 	for (t.tv_sec = 4; t.tv_sec <= 14; t.tv_sec += 2) {
    304  1.1      cgd 		for (i = 0; i < nets; i++) {
    305  1.1      cgd 			baddr.sin_addr = addrs[i];
    306  1.1      cgd 			if (sendto(sock, outbuf, outlen, 0,
    307  1.1      cgd 				(struct sockaddr *)&baddr,
    308  1.1      cgd 				sizeof (struct sockaddr)) != outlen) {
    309  1.1      cgd 				perror("Cannot send broadcast packet");
    310  1.1      cgd 				stat = RPC_CANTSEND;
    311  1.1      cgd 				goto done_broad;
    312  1.1      cgd 			}
    313  1.1      cgd 		}
    314  1.1      cgd 		if (eachresult == NULL) {
    315  1.1      cgd 			stat = RPC_SUCCESS;
    316  1.1      cgd 			goto done_broad;
    317  1.1      cgd 		}
    318  1.1      cgd 	recv_again:
    319  1.1      cgd 		msg.acpted_rply.ar_verf = _null_auth;
    320  1.1      cgd 		msg.acpted_rply.ar_results.where = (caddr_t)&r;
    321  1.1      cgd                 msg.acpted_rply.ar_results.proc = xdr_rmtcallres;
    322  1.1      cgd 		readfds = mask;
    323  1.2  deraadt 		switch (select(sock+1, &readfds, (int *)NULL,
    324  1.1      cgd 			       (int *)NULL, &t)) {
    325  1.1      cgd 
    326  1.1      cgd 		case 0:  /* timed out */
    327  1.1      cgd 			stat = RPC_TIMEDOUT;
    328  1.1      cgd 			continue;
    329  1.1      cgd 
    330  1.1      cgd 		case -1:  /* some kind of error */
    331  1.1      cgd 			if (errno == EINTR)
    332  1.1      cgd 				goto recv_again;
    333  1.1      cgd 			perror("Broadcast select problem");
    334  1.1      cgd 			stat = RPC_CANTRECV;
    335  1.1      cgd 			goto done_broad;
    336  1.1      cgd 
    337  1.1      cgd 		}  /* end of select results switch */
    338  1.1      cgd 	try_again:
    339  1.1      cgd 		fromlen = sizeof(struct sockaddr);
    340  1.1      cgd 		inlen = recvfrom(sock, inbuf, UDPMSGSIZE, 0,
    341  1.1      cgd 			(struct sockaddr *)&raddr, &fromlen);
    342  1.1      cgd 		if (inlen < 0) {
    343  1.1      cgd 			if (errno == EINTR)
    344  1.1      cgd 				goto try_again;
    345  1.1      cgd 			perror("Cannot receive reply to broadcast");
    346  1.1      cgd 			stat = RPC_CANTRECV;
    347  1.1      cgd 			goto done_broad;
    348  1.1      cgd 		}
    349  1.3      cgd 		if (inlen < sizeof(u_int32_t))
    350  1.1      cgd 			goto recv_again;
    351  1.1      cgd 		/*
    352  1.1      cgd 		 * see if reply transaction id matches sent id.
    353  1.1      cgd 		 * If so, decode the results.
    354  1.1      cgd 		 */
    355  1.1      cgd 		xdrmem_create(xdrs, inbuf, (u_int)inlen, XDR_DECODE);
    356  1.1      cgd 		if (xdr_replymsg(xdrs, &msg)) {
    357  1.1      cgd 			if ((msg.rm_xid == xid) &&
    358  1.1      cgd 				(msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
    359  1.1      cgd 				(msg.acpted_rply.ar_stat == SUCCESS)) {
    360  1.1      cgd 				raddr.sin_port = htons((u_short)port);
    361  1.1      cgd 				done = (*eachresult)(resultsp, &raddr);
    362  1.1      cgd 			}
    363  1.1      cgd 			/* otherwise, we just ignore the errors ... */
    364  1.1      cgd 		} else {
    365  1.1      cgd #ifdef notdef
    366  1.1      cgd 			/* some kind of deserialization problem ... */
    367  1.1      cgd 			if (msg.rm_xid == xid)
    368  1.1      cgd 				fprintf(stderr, "Broadcast deserialization problem");
    369  1.1      cgd 			/* otherwise, just random garbage */
    370  1.1      cgd #endif
    371  1.1      cgd 		}
    372  1.1      cgd 		xdrs->x_op = XDR_FREE;
    373  1.1      cgd 		msg.acpted_rply.ar_results.proc = xdr_void;
    374  1.1      cgd 		(void)xdr_replymsg(xdrs, &msg);
    375  1.1      cgd 		(void)(*xresults)(xdrs, resultsp);
    376  1.1      cgd 		xdr_destroy(xdrs);
    377  1.1      cgd 		if (done) {
    378  1.1      cgd 			stat = RPC_SUCCESS;
    379  1.1      cgd 			goto done_broad;
    380  1.1      cgd 		} else {
    381  1.1      cgd 			goto recv_again;
    382  1.1      cgd 		}
    383  1.1      cgd 	}
    384  1.1      cgd done_broad:
    385  1.1      cgd 	(void)close(sock);
    386  1.1      cgd 	AUTH_DESTROY(unix_auth);
    387  1.1      cgd 	return (stat);
    388  1.1      cgd }
    389  1.1      cgd 
    390