18360efbdSAlfred Perlstein /* $NetBSD: svc_vc.c,v 1.7 2000/08/03 00:01:53 fvdl Exp $ */ 28360efbdSAlfred Perlstein 38360efbdSAlfred Perlstein /* 48360efbdSAlfred Perlstein * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 58360efbdSAlfred Perlstein * unrestricted use provided that this legend is included on all tape 68360efbdSAlfred Perlstein * media and as a part of the software program in whole or part. Users 78360efbdSAlfred Perlstein * may copy or modify Sun RPC without charge, but are not authorized 88360efbdSAlfred Perlstein * to license or distribute it to anyone else except as part of a product or 98360efbdSAlfred Perlstein * program developed by the user. 108360efbdSAlfred Perlstein * 118360efbdSAlfred Perlstein * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 128360efbdSAlfred Perlstein * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 138360efbdSAlfred Perlstein * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 148360efbdSAlfred Perlstein * 158360efbdSAlfred Perlstein * Sun RPC is provided with no support and without any obligation on the 168360efbdSAlfred Perlstein * part of Sun Microsystems, Inc. to assist in its use, correction, 178360efbdSAlfred Perlstein * modification or enhancement. 188360efbdSAlfred Perlstein * 198360efbdSAlfred Perlstein * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 208360efbdSAlfred Perlstein * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 218360efbdSAlfred Perlstein * OR ANY PART THEREOF. 228360efbdSAlfred Perlstein * 238360efbdSAlfred Perlstein * In no event will Sun Microsystems, Inc. be liable for any lost revenue 248360efbdSAlfred Perlstein * or profits or other special, indirect and consequential damages, even if 258360efbdSAlfred Perlstein * Sun has been advised of the possibility of such damages. 268360efbdSAlfred Perlstein * 278360efbdSAlfred Perlstein * Sun Microsystems, Inc. 288360efbdSAlfred Perlstein * 2550 Garcia Avenue 298360efbdSAlfred Perlstein * Mountain View, California 94043 308360efbdSAlfred Perlstein */ 318360efbdSAlfred Perlstein 328360efbdSAlfred Perlstein #if defined(LIBC_SCCS) && !defined(lint) 338360efbdSAlfred Perlstein static char *sccsid = "@(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro"; 348360efbdSAlfred Perlstein static char *sccsid = "@(#)svc_tcp.c 2.2 88/08/01 4.0 RPCSRC"; 358360efbdSAlfred Perlstein #endif 36d3d20c82SDavid E. O'Brien #include <sys/cdefs.h> 37d3d20c82SDavid E. O'Brien __FBSDID("$FreeBSD$"); 388360efbdSAlfred Perlstein 398360efbdSAlfred Perlstein /* 408360efbdSAlfred Perlstein * svc_vc.c, Server side for Connection Oriented based RPC. 418360efbdSAlfred Perlstein * 428360efbdSAlfred Perlstein * Actually implements two flavors of transporter - 438360efbdSAlfred Perlstein * a tcp rendezvouser (a listner and connection establisher) 448360efbdSAlfred Perlstein * and a record/tcp stream. 458360efbdSAlfred Perlstein */ 468360efbdSAlfred Perlstein 478360efbdSAlfred Perlstein #include "namespace.h" 489f5afc13SIan Dowse #include "reentrant.h" 498360efbdSAlfred Perlstein #include <sys/types.h> 508360efbdSAlfred Perlstein #include <sys/param.h> 518360efbdSAlfred Perlstein #include <sys/poll.h> 528360efbdSAlfred Perlstein #include <sys/socket.h> 538360efbdSAlfred Perlstein #include <sys/un.h> 5408497c02SMartin Blapp #include <sys/time.h> 558360efbdSAlfred Perlstein #include <sys/uio.h> 568360efbdSAlfred Perlstein #include <netinet/in.h> 578360efbdSAlfred Perlstein #include <netinet/tcp.h> 588360efbdSAlfred Perlstein 598360efbdSAlfred Perlstein #include <assert.h> 608360efbdSAlfred Perlstein #include <err.h> 618360efbdSAlfred Perlstein #include <errno.h> 6208497c02SMartin Blapp #include <fcntl.h> 638360efbdSAlfred Perlstein #include <stdio.h> 648360efbdSAlfred Perlstein #include <stdlib.h> 658360efbdSAlfred Perlstein #include <string.h> 668360efbdSAlfred Perlstein #include <unistd.h> 678360efbdSAlfred Perlstein 688360efbdSAlfred Perlstein #include <rpc/rpc.h> 698360efbdSAlfred Perlstein 708360efbdSAlfred Perlstein #include "rpc_com.h" 718360efbdSAlfred Perlstein #include "un-namespace.h" 728360efbdSAlfred Perlstein 7308497c02SMartin Blapp extern rwlock_t svc_fd_lock; 7408497c02SMartin Blapp 75c05ac53bSDavid E. O'Brien static SVCXPRT *makefd_xprt(int, u_int, u_int); 76c05ac53bSDavid E. O'Brien static bool_t rendezvous_request(SVCXPRT *, struct rpc_msg *); 77c05ac53bSDavid E. O'Brien static enum xprt_stat rendezvous_stat(SVCXPRT *); 78c05ac53bSDavid E. O'Brien static void svc_vc_destroy(SVCXPRT *); 7908497c02SMartin Blapp static void __svc_vc_dodestroy (SVCXPRT *); 80f249dbccSDag-Erling Smørgrav static int read_vc(void *, void *, int); 81f249dbccSDag-Erling Smørgrav static int write_vc(void *, void *, int); 82c05ac53bSDavid E. O'Brien static enum xprt_stat svc_vc_stat(SVCXPRT *); 83c05ac53bSDavid E. O'Brien static bool_t svc_vc_recv(SVCXPRT *, struct rpc_msg *); 84f249dbccSDag-Erling Smørgrav static bool_t svc_vc_getargs(SVCXPRT *, xdrproc_t, void *); 85f249dbccSDag-Erling Smørgrav static bool_t svc_vc_freeargs(SVCXPRT *, xdrproc_t, void *); 86c05ac53bSDavid E. O'Brien static bool_t svc_vc_reply(SVCXPRT *, struct rpc_msg *); 87c05ac53bSDavid E. O'Brien static void svc_vc_rendezvous_ops(SVCXPRT *); 88c05ac53bSDavid E. O'Brien static void svc_vc_ops(SVCXPRT *); 89c05ac53bSDavid E. O'Brien static bool_t svc_vc_control(SVCXPRT *xprt, const u_int rq, void *in); 9008497c02SMartin Blapp static bool_t svc_vc_rendezvous_control (SVCXPRT *xprt, const u_int rq, 9108497c02SMartin Blapp void *in); 928360efbdSAlfred Perlstein 938360efbdSAlfred Perlstein struct cf_rendezvous { /* kept in xprt->xp_p1 for rendezvouser */ 948360efbdSAlfred Perlstein u_int sendsize; 958360efbdSAlfred Perlstein u_int recvsize; 9608497c02SMartin Blapp int maxrec; 978360efbdSAlfred Perlstein }; 988360efbdSAlfred Perlstein 998360efbdSAlfred Perlstein struct cf_conn { /* kept in xprt->xp_p1 for actual connection */ 1008360efbdSAlfred Perlstein enum xprt_stat strm_stat; 1018360efbdSAlfred Perlstein u_int32_t x_id; 1028360efbdSAlfred Perlstein XDR xdrs; 1038360efbdSAlfred Perlstein char verf_body[MAX_AUTH_BYTES]; 10408497c02SMartin Blapp u_int sendsize; 10508497c02SMartin Blapp u_int recvsize; 10608497c02SMartin Blapp int maxrec; 10708497c02SMartin Blapp bool_t nonblock; 10808497c02SMartin Blapp struct timeval last_recv_time; 1098360efbdSAlfred Perlstein }; 1108360efbdSAlfred Perlstein 1118360efbdSAlfred Perlstein /* 1128360efbdSAlfred Perlstein * Usage: 1138360efbdSAlfred Perlstein * xprt = svc_vc_create(sock, send_buf_size, recv_buf_size); 1148360efbdSAlfred Perlstein * 1158360efbdSAlfred Perlstein * Creates, registers, and returns a (rpc) tcp based transporter. 1168360efbdSAlfred Perlstein * Once *xprt is initialized, it is registered as a transporter 1178360efbdSAlfred Perlstein * see (svc.h, xprt_register). This routine returns 1188360efbdSAlfred Perlstein * a NULL if a problem occurred. 1198360efbdSAlfred Perlstein * 1208360efbdSAlfred Perlstein * The filedescriptor passed in is expected to refer to a bound, but 1218360efbdSAlfred Perlstein * not yet connected socket. 1228360efbdSAlfred Perlstein * 1238360efbdSAlfred Perlstein * Since streams do buffered io similar to stdio, the caller can specify 1248360efbdSAlfred Perlstein * how big the send and receive buffers are via the second and third parms; 1258360efbdSAlfred Perlstein * 0 => use the system default. 1268360efbdSAlfred Perlstein */ 1278360efbdSAlfred Perlstein SVCXPRT * 1288360efbdSAlfred Perlstein svc_vc_create(fd, sendsize, recvsize) 1298360efbdSAlfred Perlstein int fd; 1308360efbdSAlfred Perlstein u_int sendsize; 1318360efbdSAlfred Perlstein u_int recvsize; 1328360efbdSAlfred Perlstein { 1338360efbdSAlfred Perlstein SVCXPRT *xprt; 1348360efbdSAlfred Perlstein struct cf_rendezvous *r = NULL; 1358360efbdSAlfred Perlstein struct __rpc_sockinfo si; 1368360efbdSAlfred Perlstein struct sockaddr_storage sslocal; 1378360efbdSAlfred Perlstein socklen_t slen; 1388360efbdSAlfred Perlstein 1398360efbdSAlfred Perlstein r = mem_alloc(sizeof(*r)); 1408360efbdSAlfred Perlstein if (r == NULL) { 1418360efbdSAlfred Perlstein warnx("svc_vc_create: out of memory"); 1428360efbdSAlfred Perlstein goto cleanup_svc_vc_create; 1438360efbdSAlfred Perlstein } 1448360efbdSAlfred Perlstein if (!__rpc_fd2sockinfo(fd, &si)) 1458360efbdSAlfred Perlstein return NULL; 1468360efbdSAlfred Perlstein r->sendsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsize); 1478360efbdSAlfred Perlstein r->recvsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsize); 14808497c02SMartin Blapp r->maxrec = __svc_maxrec; 1498360efbdSAlfred Perlstein xprt = mem_alloc(sizeof(SVCXPRT)); 1508360efbdSAlfred Perlstein if (xprt == NULL) { 1518360efbdSAlfred Perlstein warnx("svc_vc_create: out of memory"); 1528360efbdSAlfred Perlstein goto cleanup_svc_vc_create; 1538360efbdSAlfred Perlstein } 1548360efbdSAlfred Perlstein xprt->xp_tp = NULL; 155f249dbccSDag-Erling Smørgrav xprt->xp_p1 = r; 1568360efbdSAlfred Perlstein xprt->xp_p2 = NULL; 1578360efbdSAlfred Perlstein xprt->xp_p3 = NULL; 1588360efbdSAlfred Perlstein xprt->xp_verf = _null_auth; 1598360efbdSAlfred Perlstein svc_vc_rendezvous_ops(xprt); 1608360efbdSAlfred Perlstein xprt->xp_port = (u_short)-1; /* It is the rendezvouser */ 1618360efbdSAlfred Perlstein xprt->xp_fd = fd; 1628360efbdSAlfred Perlstein 1638360efbdSAlfred Perlstein slen = sizeof (struct sockaddr_storage); 1648360efbdSAlfred Perlstein if (_getsockname(fd, (struct sockaddr *)(void *)&sslocal, &slen) < 0) { 1658360efbdSAlfred Perlstein warnx("svc_vc_create: could not retrieve local addr"); 1668360efbdSAlfred Perlstein goto cleanup_svc_vc_create; 1678360efbdSAlfred Perlstein } 1688360efbdSAlfred Perlstein 1698360efbdSAlfred Perlstein xprt->xp_ltaddr.maxlen = xprt->xp_ltaddr.len = sslocal.ss_len; 1708360efbdSAlfred Perlstein xprt->xp_ltaddr.buf = mem_alloc((size_t)sslocal.ss_len); 1718360efbdSAlfred Perlstein if (xprt->xp_ltaddr.buf == NULL) { 1728360efbdSAlfred Perlstein warnx("svc_vc_create: no mem for local addr"); 1738360efbdSAlfred Perlstein goto cleanup_svc_vc_create; 1748360efbdSAlfred Perlstein } 1758360efbdSAlfred Perlstein memcpy(xprt->xp_ltaddr.buf, &sslocal, (size_t)sslocal.ss_len); 1768360efbdSAlfred Perlstein 1778360efbdSAlfred Perlstein xprt->xp_rtaddr.maxlen = sizeof (struct sockaddr_storage); 1788360efbdSAlfred Perlstein xprt_register(xprt); 1798360efbdSAlfred Perlstein return (xprt); 1808360efbdSAlfred Perlstein cleanup_svc_vc_create: 1818360efbdSAlfred Perlstein if (r != NULL) 1828360efbdSAlfred Perlstein mem_free(r, sizeof(*r)); 1838360efbdSAlfred Perlstein return (NULL); 1848360efbdSAlfred Perlstein } 1858360efbdSAlfred Perlstein 1868360efbdSAlfred Perlstein /* 1878360efbdSAlfred Perlstein * Like svtcp_create(), except the routine takes any *open* UNIX file 1888360efbdSAlfred Perlstein * descriptor as its first input. 1898360efbdSAlfred Perlstein */ 1908360efbdSAlfred Perlstein SVCXPRT * 1918360efbdSAlfred Perlstein svc_fd_create(fd, sendsize, recvsize) 1928360efbdSAlfred Perlstein int fd; 1938360efbdSAlfred Perlstein u_int sendsize; 1948360efbdSAlfred Perlstein u_int recvsize; 1958360efbdSAlfred Perlstein { 1968360efbdSAlfred Perlstein struct sockaddr_storage ss; 1978360efbdSAlfred Perlstein socklen_t slen; 1988360efbdSAlfred Perlstein SVCXPRT *ret; 1998360efbdSAlfred Perlstein 2008360efbdSAlfred Perlstein assert(fd != -1); 2018360efbdSAlfred Perlstein 2028360efbdSAlfred Perlstein ret = makefd_xprt(fd, sendsize, recvsize); 2038360efbdSAlfred Perlstein if (ret == NULL) 2048360efbdSAlfred Perlstein return NULL; 2058360efbdSAlfred Perlstein 2068360efbdSAlfred Perlstein slen = sizeof (struct sockaddr_storage); 2078360efbdSAlfred Perlstein if (_getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) { 2088360efbdSAlfred Perlstein warnx("svc_fd_create: could not retrieve local addr"); 2098360efbdSAlfred Perlstein goto freedata; 2108360efbdSAlfred Perlstein } 2118360efbdSAlfred Perlstein ret->xp_ltaddr.maxlen = ret->xp_ltaddr.len = ss.ss_len; 2128360efbdSAlfred Perlstein ret->xp_ltaddr.buf = mem_alloc((size_t)ss.ss_len); 2138360efbdSAlfred Perlstein if (ret->xp_ltaddr.buf == NULL) { 2148360efbdSAlfred Perlstein warnx("svc_fd_create: no mem for local addr"); 2158360efbdSAlfred Perlstein goto freedata; 2168360efbdSAlfred Perlstein } 2178360efbdSAlfred Perlstein memcpy(ret->xp_ltaddr.buf, &ss, (size_t)ss.ss_len); 2188360efbdSAlfred Perlstein 2198360efbdSAlfred Perlstein slen = sizeof (struct sockaddr_storage); 2208360efbdSAlfred Perlstein if (_getpeername(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) { 2218360efbdSAlfred Perlstein warnx("svc_fd_create: could not retrieve remote addr"); 2228360efbdSAlfred Perlstein goto freedata; 2238360efbdSAlfred Perlstein } 2248360efbdSAlfred Perlstein ret->xp_rtaddr.maxlen = ret->xp_rtaddr.len = ss.ss_len; 2258360efbdSAlfred Perlstein ret->xp_rtaddr.buf = mem_alloc((size_t)ss.ss_len); 2268360efbdSAlfred Perlstein if (ret->xp_rtaddr.buf == NULL) { 2278360efbdSAlfred Perlstein warnx("svc_fd_create: no mem for local addr"); 2288360efbdSAlfred Perlstein goto freedata; 2298360efbdSAlfred Perlstein } 2308360efbdSAlfred Perlstein memcpy(ret->xp_rtaddr.buf, &ss, (size_t)ss.ss_len); 2318360efbdSAlfred Perlstein #ifdef PORTMAP 2322abd9cf1SAlfred Perlstein if (ss.ss_family == AF_INET || ss.ss_family == AF_LOCAL) { 2338360efbdSAlfred Perlstein ret->xp_raddr = *(struct sockaddr_in *)ret->xp_rtaddr.buf; 2348360efbdSAlfred Perlstein ret->xp_addrlen = sizeof (struct sockaddr_in); 2358360efbdSAlfred Perlstein } 2368360efbdSAlfred Perlstein #endif /* PORTMAP */ 2378360efbdSAlfred Perlstein 2388360efbdSAlfred Perlstein return ret; 2398360efbdSAlfred Perlstein 2408360efbdSAlfred Perlstein freedata: 2418360efbdSAlfred Perlstein if (ret->xp_ltaddr.buf != NULL) 2428360efbdSAlfred Perlstein mem_free(ret->xp_ltaddr.buf, rep->xp_ltaddr.maxlen); 2438360efbdSAlfred Perlstein 2448360efbdSAlfred Perlstein return NULL; 2458360efbdSAlfred Perlstein } 2468360efbdSAlfred Perlstein 2478360efbdSAlfred Perlstein static SVCXPRT * 2488360efbdSAlfred Perlstein makefd_xprt(fd, sendsize, recvsize) 2498360efbdSAlfred Perlstein int fd; 2508360efbdSAlfred Perlstein u_int sendsize; 2518360efbdSAlfred Perlstein u_int recvsize; 2528360efbdSAlfred Perlstein { 2538360efbdSAlfred Perlstein SVCXPRT *xprt; 2548360efbdSAlfred Perlstein struct cf_conn *cd; 2558360efbdSAlfred Perlstein const char *netid; 2568360efbdSAlfred Perlstein struct __rpc_sockinfo si; 2578360efbdSAlfred Perlstein 2588360efbdSAlfred Perlstein assert(fd != -1); 2598360efbdSAlfred Perlstein 2608360efbdSAlfred Perlstein xprt = mem_alloc(sizeof(SVCXPRT)); 2618360efbdSAlfred Perlstein if (xprt == NULL) { 2628360efbdSAlfred Perlstein warnx("svc_vc: makefd_xprt: out of memory"); 2638360efbdSAlfred Perlstein goto done; 2648360efbdSAlfred Perlstein } 2658360efbdSAlfred Perlstein memset(xprt, 0, sizeof *xprt); 2668360efbdSAlfred Perlstein cd = mem_alloc(sizeof(struct cf_conn)); 2678360efbdSAlfred Perlstein if (cd == NULL) { 2688360efbdSAlfred Perlstein warnx("svc_tcp: makefd_xprt: out of memory"); 2698360efbdSAlfred Perlstein mem_free(xprt, sizeof(SVCXPRT)); 2708360efbdSAlfred Perlstein xprt = NULL; 2718360efbdSAlfred Perlstein goto done; 2728360efbdSAlfred Perlstein } 2738360efbdSAlfred Perlstein cd->strm_stat = XPRT_IDLE; 2748360efbdSAlfred Perlstein xdrrec_create(&(cd->xdrs), sendsize, recvsize, 275f249dbccSDag-Erling Smørgrav xprt, read_vc, write_vc); 276f249dbccSDag-Erling Smørgrav xprt->xp_p1 = cd; 2778360efbdSAlfred Perlstein xprt->xp_verf.oa_base = cd->verf_body; 2788360efbdSAlfred Perlstein svc_vc_ops(xprt); /* truely deals with calls */ 2798360efbdSAlfred Perlstein xprt->xp_port = 0; /* this is a connection, not a rendezvouser */ 2808360efbdSAlfred Perlstein xprt->xp_fd = fd; 2818360efbdSAlfred Perlstein if (__rpc_fd2sockinfo(fd, &si) && __rpc_sockinfo2netid(&si, &netid)) 2828360efbdSAlfred Perlstein xprt->xp_netid = strdup(netid); 2838360efbdSAlfred Perlstein 2848360efbdSAlfred Perlstein xprt_register(xprt); 2858360efbdSAlfred Perlstein done: 2868360efbdSAlfred Perlstein return (xprt); 2878360efbdSAlfred Perlstein } 2888360efbdSAlfred Perlstein 2898360efbdSAlfred Perlstein /*ARGSUSED*/ 2908360efbdSAlfred Perlstein static bool_t 2918360efbdSAlfred Perlstein rendezvous_request(xprt, msg) 2928360efbdSAlfred Perlstein SVCXPRT *xprt; 2938360efbdSAlfred Perlstein struct rpc_msg *msg; 2948360efbdSAlfred Perlstein { 29508497c02SMartin Blapp int sock, flags; 2968360efbdSAlfred Perlstein struct cf_rendezvous *r; 29708497c02SMartin Blapp struct cf_conn *cd; 2988360efbdSAlfred Perlstein struct sockaddr_storage addr; 2998360efbdSAlfred Perlstein socklen_t len; 3008360efbdSAlfred Perlstein struct __rpc_sockinfo si; 30108497c02SMartin Blapp SVCXPRT *newxprt; 30208497c02SMartin Blapp fd_set cleanfds; 3038360efbdSAlfred Perlstein 3048360efbdSAlfred Perlstein assert(xprt != NULL); 3058360efbdSAlfred Perlstein assert(msg != NULL); 3068360efbdSAlfred Perlstein 3078360efbdSAlfred Perlstein r = (struct cf_rendezvous *)xprt->xp_p1; 3088360efbdSAlfred Perlstein again: 3098360efbdSAlfred Perlstein len = sizeof addr; 3108360efbdSAlfred Perlstein if ((sock = _accept(xprt->xp_fd, (struct sockaddr *)(void *)&addr, 3118360efbdSAlfred Perlstein &len)) < 0) { 3128360efbdSAlfred Perlstein if (errno == EINTR) 3138360efbdSAlfred Perlstein goto again; 31408497c02SMartin Blapp /* 31508497c02SMartin Blapp * Clean out the most idle file descriptor when we're 31608497c02SMartin Blapp * running out. 31708497c02SMartin Blapp */ 31808497c02SMartin Blapp if (errno == EMFILE || errno == ENFILE) { 31908497c02SMartin Blapp cleanfds = svc_fdset; 32008497c02SMartin Blapp __svc_clean_idle(&cleanfds, 0, FALSE); 32108497c02SMartin Blapp goto again; 32208497c02SMartin Blapp } 3238360efbdSAlfred Perlstein return (FALSE); 3248360efbdSAlfred Perlstein } 3258360efbdSAlfred Perlstein /* 3268360efbdSAlfred Perlstein * make a new transporter (re-uses xprt) 3278360efbdSAlfred Perlstein */ 32808497c02SMartin Blapp newxprt = makefd_xprt(sock, r->sendsize, r->recvsize); 32908497c02SMartin Blapp newxprt->xp_rtaddr.buf = mem_alloc(len); 33008497c02SMartin Blapp if (newxprt->xp_rtaddr.buf == NULL) 3318360efbdSAlfred Perlstein return (FALSE); 33208497c02SMartin Blapp memcpy(newxprt->xp_rtaddr.buf, &addr, len); 33308497c02SMartin Blapp newxprt->xp_rtaddr.len = len; 3348360efbdSAlfred Perlstein #ifdef PORTMAP 335866e3c90SAlfred Perlstein if (addr.ss_family == AF_INET || addr.ss_family == AF_LOCAL) { 33608497c02SMartin Blapp newxprt->xp_raddr = *(struct sockaddr_in *)newxprt->xp_rtaddr.buf; 33708497c02SMartin Blapp newxprt->xp_addrlen = sizeof (struct sockaddr_in); 3388360efbdSAlfred Perlstein } 3398360efbdSAlfred Perlstein #endif /* PORTMAP */ 3408360efbdSAlfred Perlstein if (__rpc_fd2sockinfo(sock, &si) && si.si_proto == IPPROTO_TCP) { 3418360efbdSAlfred Perlstein len = 1; 3428360efbdSAlfred Perlstein /* XXX fvdl - is this useful? */ 3438360efbdSAlfred Perlstein _setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &len, sizeof (len)); 3448360efbdSAlfred Perlstein } 34508497c02SMartin Blapp 34608497c02SMartin Blapp cd = (struct cf_conn *)newxprt->xp_p1; 34708497c02SMartin Blapp 34808497c02SMartin Blapp cd->recvsize = r->recvsize; 34908497c02SMartin Blapp cd->sendsize = r->sendsize; 35008497c02SMartin Blapp cd->maxrec = r->maxrec; 35108497c02SMartin Blapp 35208497c02SMartin Blapp if (cd->maxrec != 0) { 3530ae0e1eaSMartin Blapp flags = _fcntl(sock, F_GETFL, 0); 35408497c02SMartin Blapp if (flags == -1) 35508497c02SMartin Blapp return (FALSE); 3560ae0e1eaSMartin Blapp if (_fcntl(sock, F_SETFL, flags | O_NONBLOCK) == -1) 35708497c02SMartin Blapp return (FALSE); 35808497c02SMartin Blapp if (cd->recvsize > cd->maxrec) 35908497c02SMartin Blapp cd->recvsize = cd->maxrec; 36008497c02SMartin Blapp cd->nonblock = TRUE; 36108497c02SMartin Blapp __xdrrec_setnonblock(&cd->xdrs, cd->maxrec); 36208497c02SMartin Blapp } else 36308497c02SMartin Blapp cd->nonblock = FALSE; 36408497c02SMartin Blapp 36508497c02SMartin Blapp gettimeofday(&cd->last_recv_time, NULL); 36608497c02SMartin Blapp 3678360efbdSAlfred Perlstein return (FALSE); /* there is never an rpc msg to be processed */ 3688360efbdSAlfred Perlstein } 3698360efbdSAlfred Perlstein 3708360efbdSAlfred Perlstein /*ARGSUSED*/ 3718360efbdSAlfred Perlstein static enum xprt_stat 3728360efbdSAlfred Perlstein rendezvous_stat(xprt) 3738360efbdSAlfred Perlstein SVCXPRT *xprt; 3748360efbdSAlfred Perlstein { 3758360efbdSAlfred Perlstein 3768360efbdSAlfred Perlstein return (XPRT_IDLE); 3778360efbdSAlfred Perlstein } 3788360efbdSAlfred Perlstein 3798360efbdSAlfred Perlstein static void 3808360efbdSAlfred Perlstein svc_vc_destroy(xprt) 3818360efbdSAlfred Perlstein SVCXPRT *xprt; 3828360efbdSAlfred Perlstein { 38308497c02SMartin Blapp assert(xprt != NULL); 38408497c02SMartin Blapp 38508497c02SMartin Blapp xprt_unregister(xprt); 38608497c02SMartin Blapp __svc_vc_dodestroy(xprt); 38708497c02SMartin Blapp } 38808497c02SMartin Blapp 38908497c02SMartin Blapp static void 39008497c02SMartin Blapp __svc_vc_dodestroy(xprt) 39108497c02SMartin Blapp SVCXPRT *xprt; 39208497c02SMartin Blapp { 3938360efbdSAlfred Perlstein struct cf_conn *cd; 3948360efbdSAlfred Perlstein struct cf_rendezvous *r; 3958360efbdSAlfred Perlstein 3968360efbdSAlfred Perlstein cd = (struct cf_conn *)xprt->xp_p1; 3978360efbdSAlfred Perlstein 3988360efbdSAlfred Perlstein if (xprt->xp_fd != RPC_ANYFD) 3998360efbdSAlfred Perlstein (void)_close(xprt->xp_fd); 4008360efbdSAlfred Perlstein if (xprt->xp_port != 0) { 4018360efbdSAlfred Perlstein /* a rendezvouser socket */ 4028360efbdSAlfred Perlstein r = (struct cf_rendezvous *)xprt->xp_p1; 4038360efbdSAlfred Perlstein mem_free(r, sizeof (struct cf_rendezvous)); 4048360efbdSAlfred Perlstein xprt->xp_port = 0; 4058360efbdSAlfred Perlstein } else { 4068360efbdSAlfred Perlstein /* an actual connection socket */ 4078360efbdSAlfred Perlstein XDR_DESTROY(&(cd->xdrs)); 4088360efbdSAlfred Perlstein mem_free(cd, sizeof(struct cf_conn)); 4098360efbdSAlfred Perlstein } 4108360efbdSAlfred Perlstein if (xprt->xp_rtaddr.buf) 4118360efbdSAlfred Perlstein mem_free(xprt->xp_rtaddr.buf, xprt->xp_rtaddr.maxlen); 4128360efbdSAlfred Perlstein if (xprt->xp_ltaddr.buf) 4138360efbdSAlfred Perlstein mem_free(xprt->xp_ltaddr.buf, xprt->xp_ltaddr.maxlen); 4148360efbdSAlfred Perlstein if (xprt->xp_tp) 4158360efbdSAlfred Perlstein free(xprt->xp_tp); 4168360efbdSAlfred Perlstein if (xprt->xp_netid) 4178360efbdSAlfred Perlstein free(xprt->xp_netid); 4188360efbdSAlfred Perlstein mem_free(xprt, sizeof(SVCXPRT)); 4198360efbdSAlfred Perlstein } 4208360efbdSAlfred Perlstein 4218360efbdSAlfred Perlstein /*ARGSUSED*/ 4228360efbdSAlfred Perlstein static bool_t 4238360efbdSAlfred Perlstein svc_vc_control(xprt, rq, in) 4248360efbdSAlfred Perlstein SVCXPRT *xprt; 4258360efbdSAlfred Perlstein const u_int rq; 4268360efbdSAlfred Perlstein void *in; 4278360efbdSAlfred Perlstein { 4288360efbdSAlfred Perlstein return (FALSE); 4298360efbdSAlfred Perlstein } 4308360efbdSAlfred Perlstein 43108497c02SMartin Blapp static bool_t 43208497c02SMartin Blapp svc_vc_rendezvous_control(xprt, rq, in) 43308497c02SMartin Blapp SVCXPRT *xprt; 43408497c02SMartin Blapp const u_int rq; 43508497c02SMartin Blapp void *in; 43608497c02SMartin Blapp { 43708497c02SMartin Blapp struct cf_rendezvous *cfp; 43808497c02SMartin Blapp 43908497c02SMartin Blapp cfp = (struct cf_rendezvous *)xprt->xp_p1; 44008497c02SMartin Blapp if (cfp == NULL) 44108497c02SMartin Blapp return (FALSE); 44208497c02SMartin Blapp switch (rq) { 44308497c02SMartin Blapp case SVCGET_CONNMAXREC: 44408497c02SMartin Blapp *(int *)in = cfp->maxrec; 44508497c02SMartin Blapp break; 44608497c02SMartin Blapp case SVCSET_CONNMAXREC: 44708497c02SMartin Blapp cfp->maxrec = *(int *)in; 44808497c02SMartin Blapp break; 44908497c02SMartin Blapp default: 45008497c02SMartin Blapp return (FALSE); 45108497c02SMartin Blapp } 45208497c02SMartin Blapp return (TRUE); 45308497c02SMartin Blapp } 45408497c02SMartin Blapp 4558360efbdSAlfred Perlstein /* 4568360efbdSAlfred Perlstein * reads data from the tcp or uip connection. 4578360efbdSAlfred Perlstein * any error is fatal and the connection is closed. 4588360efbdSAlfred Perlstein * (And a read of zero bytes is a half closed stream => error.) 4598360efbdSAlfred Perlstein * All read operations timeout after 35 seconds. A timeout is 4608360efbdSAlfred Perlstein * fatal for the connection. 4618360efbdSAlfred Perlstein */ 4628360efbdSAlfred Perlstein static int 4638360efbdSAlfred Perlstein read_vc(xprtp, buf, len) 464f249dbccSDag-Erling Smørgrav void *xprtp; 465f249dbccSDag-Erling Smørgrav void *buf; 4668360efbdSAlfred Perlstein int len; 4678360efbdSAlfred Perlstein { 4688360efbdSAlfred Perlstein SVCXPRT *xprt; 4698360efbdSAlfred Perlstein int sock; 4708360efbdSAlfred Perlstein int milliseconds = 35 * 1000; 4718360efbdSAlfred Perlstein struct pollfd pollfd; 47208497c02SMartin Blapp struct cf_conn *cfp; 4738360efbdSAlfred Perlstein 474f249dbccSDag-Erling Smørgrav xprt = (SVCXPRT *)xprtp; 4758360efbdSAlfred Perlstein assert(xprt != NULL); 4768360efbdSAlfred Perlstein 4778360efbdSAlfred Perlstein sock = xprt->xp_fd; 4788360efbdSAlfred Perlstein 47908497c02SMartin Blapp cfp = (struct cf_conn *)xprt->xp_p1; 48008497c02SMartin Blapp 48108497c02SMartin Blapp if (cfp->nonblock) { 4820ae0e1eaSMartin Blapp len = _read(sock, buf, (size_t)len); 48308497c02SMartin Blapp if (len < 0) { 48408497c02SMartin Blapp if (errno == EAGAIN) 48508497c02SMartin Blapp len = 0; 48608497c02SMartin Blapp else 48708497c02SMartin Blapp goto fatal_err; 48808497c02SMartin Blapp } 48908497c02SMartin Blapp if (len != 0) 49008497c02SMartin Blapp gettimeofday(&cfp->last_recv_time, NULL); 49108497c02SMartin Blapp return len; 49208497c02SMartin Blapp } 49308497c02SMartin Blapp 4948360efbdSAlfred Perlstein do { 4958360efbdSAlfred Perlstein pollfd.fd = sock; 4968360efbdSAlfred Perlstein pollfd.events = POLLIN; 4978360efbdSAlfred Perlstein pollfd.revents = 0; 4988360efbdSAlfred Perlstein switch (_poll(&pollfd, 1, milliseconds)) { 4998360efbdSAlfred Perlstein case -1: 500fa87b7eaSAlfred Perlstein if (errno == EINTR) 5018360efbdSAlfred Perlstein continue; 5028360efbdSAlfred Perlstein /*FALLTHROUGH*/ 5038360efbdSAlfred Perlstein case 0: 5048360efbdSAlfred Perlstein goto fatal_err; 5054ed6d634SAlfred Perlstein 5068360efbdSAlfred Perlstein default: 5078360efbdSAlfred Perlstein break; 5088360efbdSAlfred Perlstein } 5098360efbdSAlfred Perlstein } while ((pollfd.revents & POLLIN) == 0); 5108360efbdSAlfred Perlstein 5110ae0e1eaSMartin Blapp if ((len = _read(sock, buf, (size_t)len)) > 0) { 51208497c02SMartin Blapp gettimeofday(&cfp->last_recv_time, NULL); 5138360efbdSAlfred Perlstein return (len); 5148360efbdSAlfred Perlstein } 5158360efbdSAlfred Perlstein 5168360efbdSAlfred Perlstein fatal_err: 5178360efbdSAlfred Perlstein ((struct cf_conn *)(xprt->xp_p1))->strm_stat = XPRT_DIED; 5188360efbdSAlfred Perlstein return (-1); 5198360efbdSAlfred Perlstein } 5208360efbdSAlfred Perlstein 5218360efbdSAlfred Perlstein /* 5228360efbdSAlfred Perlstein * writes data to the tcp connection. 5238360efbdSAlfred Perlstein * Any error is fatal and the connection is closed. 5248360efbdSAlfred Perlstein */ 5258360efbdSAlfred Perlstein static int 5268360efbdSAlfred Perlstein write_vc(xprtp, buf, len) 527f249dbccSDag-Erling Smørgrav void *xprtp; 528f249dbccSDag-Erling Smørgrav void *buf; 5298360efbdSAlfred Perlstein int len; 5308360efbdSAlfred Perlstein { 5318360efbdSAlfred Perlstein SVCXPRT *xprt; 5328360efbdSAlfred Perlstein int i, cnt; 53308497c02SMartin Blapp struct cf_conn *cd; 53408497c02SMartin Blapp struct timeval tv0, tv1; 5358360efbdSAlfred Perlstein 536f249dbccSDag-Erling Smørgrav xprt = (SVCXPRT *)xprtp; 5378360efbdSAlfred Perlstein assert(xprt != NULL); 5388360efbdSAlfred Perlstein 53908497c02SMartin Blapp cd = (struct cf_conn *)xprt->xp_p1; 54008497c02SMartin Blapp 54108497c02SMartin Blapp if (cd->nonblock) 54208497c02SMartin Blapp gettimeofday(&tv0, NULL); 54308497c02SMartin Blapp 544361de173SStefan Farfeleder for (cnt = len; cnt > 0; cnt -= i, buf = (char *)buf + i) { 54508497c02SMartin Blapp i = _write(xprt->xp_fd, buf, (size_t)cnt); 54608497c02SMartin Blapp if (i < 0) { 54708497c02SMartin Blapp if (errno != EAGAIN || !cd->nonblock) { 54808497c02SMartin Blapp cd->strm_stat = XPRT_DIED; 5498360efbdSAlfred Perlstein return (-1); 5508360efbdSAlfred Perlstein } 55108497c02SMartin Blapp if (cd->nonblock && i != cnt) { 55208497c02SMartin Blapp /* 55308497c02SMartin Blapp * For non-blocking connections, do not 55408497c02SMartin Blapp * take more than 2 seconds writing the 55508497c02SMartin Blapp * data out. 55608497c02SMartin Blapp * 55708497c02SMartin Blapp * XXX 2 is an arbitrary amount. 55808497c02SMartin Blapp */ 55908497c02SMartin Blapp gettimeofday(&tv1, NULL); 56008497c02SMartin Blapp if (tv1.tv_sec - tv0.tv_sec >= 2) { 56108497c02SMartin Blapp cd->strm_stat = XPRT_DIED; 5628360efbdSAlfred Perlstein return (-1); 5638360efbdSAlfred Perlstein } 5648360efbdSAlfred Perlstein } 5658360efbdSAlfred Perlstein } 56608497c02SMartin Blapp } 5678360efbdSAlfred Perlstein 5688360efbdSAlfred Perlstein return (len); 5698360efbdSAlfred Perlstein } 5708360efbdSAlfred Perlstein 5718360efbdSAlfred Perlstein static enum xprt_stat 5728360efbdSAlfred Perlstein svc_vc_stat(xprt) 5738360efbdSAlfred Perlstein SVCXPRT *xprt; 5748360efbdSAlfred Perlstein { 5758360efbdSAlfred Perlstein struct cf_conn *cd; 5768360efbdSAlfred Perlstein 5778360efbdSAlfred Perlstein assert(xprt != NULL); 5788360efbdSAlfred Perlstein 5798360efbdSAlfred Perlstein cd = (struct cf_conn *)(xprt->xp_p1); 5808360efbdSAlfred Perlstein 5818360efbdSAlfred Perlstein if (cd->strm_stat == XPRT_DIED) 5828360efbdSAlfred Perlstein return (XPRT_DIED); 5838360efbdSAlfred Perlstein if (! xdrrec_eof(&(cd->xdrs))) 5848360efbdSAlfred Perlstein return (XPRT_MOREREQS); 5858360efbdSAlfred Perlstein return (XPRT_IDLE); 5868360efbdSAlfred Perlstein } 5878360efbdSAlfred Perlstein 5888360efbdSAlfred Perlstein static bool_t 5898360efbdSAlfred Perlstein svc_vc_recv(xprt, msg) 5908360efbdSAlfred Perlstein SVCXPRT *xprt; 5918360efbdSAlfred Perlstein struct rpc_msg *msg; 5928360efbdSAlfred Perlstein { 5938360efbdSAlfred Perlstein struct cf_conn *cd; 5948360efbdSAlfred Perlstein XDR *xdrs; 5958360efbdSAlfred Perlstein 5968360efbdSAlfred Perlstein assert(xprt != NULL); 5978360efbdSAlfred Perlstein assert(msg != NULL); 5988360efbdSAlfred Perlstein 5998360efbdSAlfred Perlstein cd = (struct cf_conn *)(xprt->xp_p1); 6008360efbdSAlfred Perlstein xdrs = &(cd->xdrs); 6018360efbdSAlfred Perlstein 60208497c02SMartin Blapp if (cd->nonblock) { 60308497c02SMartin Blapp if (!__xdrrec_getrec(xdrs, &cd->strm_stat, TRUE)) 60408497c02SMartin Blapp return FALSE; 60508497c02SMartin Blapp } 60608497c02SMartin Blapp 6078360efbdSAlfred Perlstein xdrs->x_op = XDR_DECODE; 6088360efbdSAlfred Perlstein (void)xdrrec_skiprecord(xdrs); 6098360efbdSAlfred Perlstein if (xdr_callmsg(xdrs, msg)) { 6108360efbdSAlfred Perlstein cd->x_id = msg->rm_xid; 6118360efbdSAlfred Perlstein return (TRUE); 6128360efbdSAlfred Perlstein } 6138360efbdSAlfred Perlstein cd->strm_stat = XPRT_DIED; 6148360efbdSAlfred Perlstein return (FALSE); 6158360efbdSAlfred Perlstein } 6168360efbdSAlfred Perlstein 6178360efbdSAlfred Perlstein static bool_t 6188360efbdSAlfred Perlstein svc_vc_getargs(xprt, xdr_args, args_ptr) 6198360efbdSAlfred Perlstein SVCXPRT *xprt; 6208360efbdSAlfred Perlstein xdrproc_t xdr_args; 621f249dbccSDag-Erling Smørgrav void *args_ptr; 6228360efbdSAlfred Perlstein { 6238360efbdSAlfred Perlstein 6248360efbdSAlfred Perlstein assert(xprt != NULL); 6258360efbdSAlfred Perlstein /* args_ptr may be NULL */ 6268360efbdSAlfred Perlstein return ((*xdr_args)(&(((struct cf_conn *)(xprt->xp_p1))->xdrs), 6278360efbdSAlfred Perlstein args_ptr)); 6288360efbdSAlfred Perlstein } 6298360efbdSAlfred Perlstein 6308360efbdSAlfred Perlstein static bool_t 6318360efbdSAlfred Perlstein svc_vc_freeargs(xprt, xdr_args, args_ptr) 6328360efbdSAlfred Perlstein SVCXPRT *xprt; 6338360efbdSAlfred Perlstein xdrproc_t xdr_args; 634f249dbccSDag-Erling Smørgrav void *args_ptr; 6358360efbdSAlfred Perlstein { 6368360efbdSAlfred Perlstein XDR *xdrs; 6378360efbdSAlfred Perlstein 6388360efbdSAlfred Perlstein assert(xprt != NULL); 6398360efbdSAlfred Perlstein /* args_ptr may be NULL */ 6408360efbdSAlfred Perlstein 6418360efbdSAlfred Perlstein xdrs = &(((struct cf_conn *)(xprt->xp_p1))->xdrs); 6428360efbdSAlfred Perlstein 6438360efbdSAlfred Perlstein xdrs->x_op = XDR_FREE; 6448360efbdSAlfred Perlstein return ((*xdr_args)(xdrs, args_ptr)); 6458360efbdSAlfred Perlstein } 6468360efbdSAlfred Perlstein 6478360efbdSAlfred Perlstein static bool_t 6488360efbdSAlfred Perlstein svc_vc_reply(xprt, msg) 6498360efbdSAlfred Perlstein SVCXPRT *xprt; 6508360efbdSAlfred Perlstein struct rpc_msg *msg; 6518360efbdSAlfred Perlstein { 6528360efbdSAlfred Perlstein struct cf_conn *cd; 6538360efbdSAlfred Perlstein XDR *xdrs; 65408497c02SMartin Blapp bool_t rstat; 6558360efbdSAlfred Perlstein 6568360efbdSAlfred Perlstein assert(xprt != NULL); 6578360efbdSAlfred Perlstein assert(msg != NULL); 6588360efbdSAlfred Perlstein 6598360efbdSAlfred Perlstein cd = (struct cf_conn *)(xprt->xp_p1); 6608360efbdSAlfred Perlstein xdrs = &(cd->xdrs); 6618360efbdSAlfred Perlstein 6628360efbdSAlfred Perlstein xdrs->x_op = XDR_ENCODE; 6638360efbdSAlfred Perlstein msg->rm_xid = cd->x_id; 66408497c02SMartin Blapp rstat = xdr_replymsg(xdrs, msg); 6658360efbdSAlfred Perlstein (void)xdrrec_endofrecord(xdrs, TRUE); 66608497c02SMartin Blapp return (rstat); 6678360efbdSAlfred Perlstein } 6688360efbdSAlfred Perlstein 6698360efbdSAlfred Perlstein static void 6708360efbdSAlfred Perlstein svc_vc_ops(xprt) 6718360efbdSAlfred Perlstein SVCXPRT *xprt; 6728360efbdSAlfred Perlstein { 6738360efbdSAlfred Perlstein static struct xp_ops ops; 6748360efbdSAlfred Perlstein static struct xp_ops2 ops2; 6758360efbdSAlfred Perlstein extern mutex_t ops_lock; 6768360efbdSAlfred Perlstein 6778360efbdSAlfred Perlstein /* VARIABLES PROTECTED BY ops_lock: ops, ops2 */ 6788360efbdSAlfred Perlstein 6798360efbdSAlfred Perlstein mutex_lock(&ops_lock); 6808360efbdSAlfred Perlstein if (ops.xp_recv == NULL) { 6818360efbdSAlfred Perlstein ops.xp_recv = svc_vc_recv; 6828360efbdSAlfred Perlstein ops.xp_stat = svc_vc_stat; 6838360efbdSAlfred Perlstein ops.xp_getargs = svc_vc_getargs; 6848360efbdSAlfred Perlstein ops.xp_reply = svc_vc_reply; 6858360efbdSAlfred Perlstein ops.xp_freeargs = svc_vc_freeargs; 6868360efbdSAlfred Perlstein ops.xp_destroy = svc_vc_destroy; 6878360efbdSAlfred Perlstein ops2.xp_control = svc_vc_control; 6888360efbdSAlfred Perlstein } 6898360efbdSAlfred Perlstein xprt->xp_ops = &ops; 6908360efbdSAlfred Perlstein xprt->xp_ops2 = &ops2; 6918360efbdSAlfred Perlstein mutex_unlock(&ops_lock); 6928360efbdSAlfred Perlstein } 6938360efbdSAlfred Perlstein 6948360efbdSAlfred Perlstein static void 6958360efbdSAlfred Perlstein svc_vc_rendezvous_ops(xprt) 6968360efbdSAlfred Perlstein SVCXPRT *xprt; 6978360efbdSAlfred Perlstein { 6988360efbdSAlfred Perlstein static struct xp_ops ops; 6998360efbdSAlfred Perlstein static struct xp_ops2 ops2; 7008360efbdSAlfred Perlstein extern mutex_t ops_lock; 7018360efbdSAlfred Perlstein 7028360efbdSAlfred Perlstein mutex_lock(&ops_lock); 7038360efbdSAlfred Perlstein if (ops.xp_recv == NULL) { 7048360efbdSAlfred Perlstein ops.xp_recv = rendezvous_request; 7058360efbdSAlfred Perlstein ops.xp_stat = rendezvous_stat; 7068360efbdSAlfred Perlstein ops.xp_getargs = 707f249dbccSDag-Erling Smørgrav (bool_t (*)(SVCXPRT *, xdrproc_t, void *))abort; 7088360efbdSAlfred Perlstein ops.xp_reply = 7091372519bSDavid E. O'Brien (bool_t (*)(SVCXPRT *, struct rpc_msg *))abort; 7108360efbdSAlfred Perlstein ops.xp_freeargs = 711f249dbccSDag-Erling Smørgrav (bool_t (*)(SVCXPRT *, xdrproc_t, void *))abort, 7128360efbdSAlfred Perlstein ops.xp_destroy = svc_vc_destroy; 71308497c02SMartin Blapp ops2.xp_control = svc_vc_rendezvous_control; 7148360efbdSAlfred Perlstein } 7158360efbdSAlfred Perlstein xprt->xp_ops = &ops; 7168360efbdSAlfred Perlstein xprt->xp_ops2 = &ops2; 7178360efbdSAlfred Perlstein mutex_unlock(&ops_lock); 7188360efbdSAlfred Perlstein } 7198360efbdSAlfred Perlstein 7204ed6d634SAlfred Perlstein /* 721ce9bc43cSMartin Blapp * Get the effective UID of the sending process. Used by rpcbind, keyserv 722ce9bc43cSMartin Blapp * and rpc.yppasswdd on AF_LOCAL. 7234ed6d634SAlfred Perlstein */ 7244ed6d634SAlfred Perlstein int 725ce9bc43cSMartin Blapp __rpc_get_local_uid(SVCXPRT *transp, uid_t *uid) { 726ce9bc43cSMartin Blapp int sock, ret; 727ce9bc43cSMartin Blapp gid_t egid; 728ce9bc43cSMartin Blapp uid_t euid; 729ce9bc43cSMartin Blapp struct sockaddr *sa; 73008760d5aSAlfred Perlstein 731ce9bc43cSMartin Blapp sock = transp->xp_fd; 732ce9bc43cSMartin Blapp sa = (struct sockaddr *)transp->xp_rtaddr.buf; 733ce9bc43cSMartin Blapp if (sa->sa_family == AF_LOCAL) { 734ce9bc43cSMartin Blapp ret = getpeereid(sock, &euid, &egid); 735ce9bc43cSMartin Blapp if (ret == 0) 736ce9bc43cSMartin Blapp *uid = euid; 737ce9bc43cSMartin Blapp return (ret); 738ce9bc43cSMartin Blapp } else 73908760d5aSAlfred Perlstein return (-1); 7404ed6d634SAlfred Perlstein } 74108497c02SMartin Blapp 74208497c02SMartin Blapp /* 74308497c02SMartin Blapp * Destroy xprts that have not have had any activity in 'timeout' seconds. 74408497c02SMartin Blapp * If 'cleanblock' is true, blocking connections (the default) are also 74508497c02SMartin Blapp * cleaned. If timeout is 0, the least active connection is picked. 74608497c02SMartin Blapp */ 74708497c02SMartin Blapp bool_t 74808497c02SMartin Blapp __svc_clean_idle(fd_set *fds, int timeout, bool_t cleanblock) 74908497c02SMartin Blapp { 75008497c02SMartin Blapp int i, ncleaned; 75108497c02SMartin Blapp SVCXPRT *xprt, *least_active; 75208497c02SMartin Blapp struct timeval tv, tdiff, tmax; 75308497c02SMartin Blapp struct cf_conn *cd; 75408497c02SMartin Blapp 75508497c02SMartin Blapp gettimeofday(&tv, NULL); 75608497c02SMartin Blapp tmax.tv_sec = tmax.tv_usec = 0; 75708497c02SMartin Blapp least_active = NULL; 75808497c02SMartin Blapp rwlock_wrlock(&svc_fd_lock); 75908497c02SMartin Blapp for (i = ncleaned = 0; i <= svc_maxfd; i++) { 76008497c02SMartin Blapp if (FD_ISSET(i, fds)) { 76108497c02SMartin Blapp xprt = __svc_xports[i]; 76208497c02SMartin Blapp if (xprt == NULL || xprt->xp_ops == NULL || 76308497c02SMartin Blapp xprt->xp_ops->xp_recv != svc_vc_recv) 76408497c02SMartin Blapp continue; 76508497c02SMartin Blapp cd = (struct cf_conn *)xprt->xp_p1; 76608497c02SMartin Blapp if (!cleanblock && !cd->nonblock) 76708497c02SMartin Blapp continue; 76808497c02SMartin Blapp if (timeout == 0) { 76908497c02SMartin Blapp timersub(&tv, &cd->last_recv_time, &tdiff); 77008497c02SMartin Blapp if (timercmp(&tdiff, &tmax, >)) { 77108497c02SMartin Blapp tmax = tdiff; 77208497c02SMartin Blapp least_active = xprt; 77308497c02SMartin Blapp } 77408497c02SMartin Blapp continue; 77508497c02SMartin Blapp } 77608497c02SMartin Blapp if (tv.tv_sec - cd->last_recv_time.tv_sec > timeout) { 77708497c02SMartin Blapp __xprt_unregister_unlocked(xprt); 77808497c02SMartin Blapp __svc_vc_dodestroy(xprt); 77908497c02SMartin Blapp ncleaned++; 78008497c02SMartin Blapp } 78108497c02SMartin Blapp } 78208497c02SMartin Blapp } 78308497c02SMartin Blapp if (timeout == 0 && least_active != NULL) { 78408497c02SMartin Blapp __xprt_unregister_unlocked(least_active); 78508497c02SMartin Blapp __svc_vc_dodestroy(least_active); 78608497c02SMartin Blapp ncleaned++; 78708497c02SMartin Blapp } 78808497c02SMartin Blapp rwlock_unlock(&svc_fd_lock); 78908497c02SMartin Blapp return ncleaned > 0 ? TRUE : FALSE; 79008497c02SMartin Blapp } 791