18360efbdSAlfred Perlstein /* $NetBSD: svc_vc.c,v 1.7 2000/08/03 00:01:53 fvdl Exp $ */
28360efbdSAlfred Perlstein
32e322d37SHiroki Sato /*-
48a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause
58a16b7a1SPedro F. Giffuni *
62e322d37SHiroki Sato * Copyright (c) 2009, Sun Microsystems, Inc.
72e322d37SHiroki Sato * All rights reserved.
88360efbdSAlfred Perlstein *
92e322d37SHiroki Sato * Redistribution and use in source and binary forms, with or without
102e322d37SHiroki Sato * modification, are permitted provided that the following conditions are met:
112e322d37SHiroki Sato * - Redistributions of source code must retain the above copyright notice,
122e322d37SHiroki Sato * this list of conditions and the following disclaimer.
132e322d37SHiroki Sato * - Redistributions in binary form must reproduce the above copyright notice,
142e322d37SHiroki Sato * this list of conditions and the following disclaimer in the documentation
152e322d37SHiroki Sato * and/or other materials provided with the distribution.
162e322d37SHiroki Sato * - Neither the name of Sun Microsystems, Inc. nor the names of its
172e322d37SHiroki Sato * contributors may be used to endorse or promote products derived
182e322d37SHiroki Sato * from this software without specific prior written permission.
198360efbdSAlfred Perlstein *
202e322d37SHiroki Sato * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
212e322d37SHiroki Sato * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
222e322d37SHiroki Sato * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
232e322d37SHiroki Sato * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
242e322d37SHiroki Sato * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
252e322d37SHiroki Sato * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
262e322d37SHiroki Sato * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
272e322d37SHiroki Sato * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
282e322d37SHiroki Sato * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
292e322d37SHiroki Sato * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
302e322d37SHiroki Sato * POSSIBILITY OF SUCH DAMAGE.
318360efbdSAlfred Perlstein */
328360efbdSAlfred Perlstein
338360efbdSAlfred Perlstein /*
348360efbdSAlfred Perlstein * svc_vc.c, Server side for Connection Oriented based RPC.
358360efbdSAlfred Perlstein *
368360efbdSAlfred Perlstein * Actually implements two flavors of transporter -
37*eb8ba6fbSAssume-Zhan * a tcp rendezvouser (a listener and connection establisher)
388360efbdSAlfred Perlstein * and a record/tcp stream.
398360efbdSAlfred Perlstein */
408360efbdSAlfred Perlstein
418360efbdSAlfred Perlstein #include "namespace.h"
429f5afc13SIan Dowse #include "reentrant.h"
438360efbdSAlfred Perlstein #include <sys/param.h>
448360efbdSAlfred Perlstein #include <sys/poll.h>
458360efbdSAlfred Perlstein #include <sys/socket.h>
468360efbdSAlfred Perlstein #include <sys/un.h>
4708497c02SMartin Blapp #include <sys/time.h>
488360efbdSAlfred Perlstein #include <sys/uio.h>
498360efbdSAlfred Perlstein #include <netinet/in.h>
508360efbdSAlfred Perlstein #include <netinet/tcp.h>
518360efbdSAlfred Perlstein
528360efbdSAlfred Perlstein #include <assert.h>
538360efbdSAlfred Perlstein #include <err.h>
548360efbdSAlfred Perlstein #include <errno.h>
5508497c02SMartin Blapp #include <fcntl.h>
568360efbdSAlfred Perlstein #include <stdio.h>
578360efbdSAlfred Perlstein #include <stdlib.h>
588360efbdSAlfred Perlstein #include <string.h>
598360efbdSAlfred Perlstein #include <unistd.h>
608360efbdSAlfred Perlstein
618360efbdSAlfred Perlstein #include <rpc/rpc.h>
628360efbdSAlfred Perlstein
638360efbdSAlfred Perlstein #include "rpc_com.h"
64235baf26SDaniel Eischen #include "mt_misc.h"
658360efbdSAlfred Perlstein #include "un-namespace.h"
668360efbdSAlfred Perlstein
67c05ac53bSDavid E. O'Brien static SVCXPRT *makefd_xprt(int, u_int, u_int);
68c05ac53bSDavid E. O'Brien static bool_t rendezvous_request(SVCXPRT *, struct rpc_msg *);
69c05ac53bSDavid E. O'Brien static enum xprt_stat rendezvous_stat(SVCXPRT *);
70c05ac53bSDavid E. O'Brien static void svc_vc_destroy(SVCXPRT *);
7108497c02SMartin Blapp static void __svc_vc_dodestroy (SVCXPRT *);
72f249dbccSDag-Erling Smørgrav static int read_vc(void *, void *, int);
73f249dbccSDag-Erling Smørgrav static int write_vc(void *, void *, int);
74c05ac53bSDavid E. O'Brien static enum xprt_stat svc_vc_stat(SVCXPRT *);
75c05ac53bSDavid E. O'Brien static bool_t svc_vc_recv(SVCXPRT *, struct rpc_msg *);
76f249dbccSDag-Erling Smørgrav static bool_t svc_vc_getargs(SVCXPRT *, xdrproc_t, void *);
77f249dbccSDag-Erling Smørgrav static bool_t svc_vc_freeargs(SVCXPRT *, xdrproc_t, void *);
78c05ac53bSDavid E. O'Brien static bool_t svc_vc_reply(SVCXPRT *, struct rpc_msg *);
79c05ac53bSDavid E. O'Brien static void svc_vc_rendezvous_ops(SVCXPRT *);
80c05ac53bSDavid E. O'Brien static void svc_vc_ops(SVCXPRT *);
81c05ac53bSDavid E. O'Brien static bool_t svc_vc_control(SVCXPRT *xprt, const u_int rq, void *in);
8208497c02SMartin Blapp static bool_t svc_vc_rendezvous_control (SVCXPRT *xprt, const u_int rq,
8308497c02SMartin Blapp void *in);
848360efbdSAlfred Perlstein
858360efbdSAlfred Perlstein struct cf_rendezvous { /* kept in xprt->xp_p1 for rendezvouser */
868360efbdSAlfred Perlstein u_int sendsize;
878360efbdSAlfred Perlstein u_int recvsize;
8808497c02SMartin Blapp int maxrec;
898360efbdSAlfred Perlstein };
908360efbdSAlfred Perlstein
918360efbdSAlfred Perlstein struct cf_conn { /* kept in xprt->xp_p1 for actual connection */
928360efbdSAlfred Perlstein enum xprt_stat strm_stat;
938360efbdSAlfred Perlstein u_int32_t x_id;
948360efbdSAlfred Perlstein XDR xdrs;
958360efbdSAlfred Perlstein char verf_body[MAX_AUTH_BYTES];
9608497c02SMartin Blapp u_int sendsize;
9708497c02SMartin Blapp u_int recvsize;
9808497c02SMartin Blapp int maxrec;
9908497c02SMartin Blapp bool_t nonblock;
10008497c02SMartin Blapp struct timeval last_recv_time;
1018360efbdSAlfred Perlstein };
1028360efbdSAlfred Perlstein
1038360efbdSAlfred Perlstein /*
1048360efbdSAlfred Perlstein * Usage:
1058360efbdSAlfred Perlstein * xprt = svc_vc_create(sock, send_buf_size, recv_buf_size);
1068360efbdSAlfred Perlstein *
1078360efbdSAlfred Perlstein * Creates, registers, and returns a (rpc) tcp based transporter.
1088360efbdSAlfred Perlstein * Once *xprt is initialized, it is registered as a transporter
1098360efbdSAlfred Perlstein * see (svc.h, xprt_register). This routine returns
1108360efbdSAlfred Perlstein * a NULL if a problem occurred.
1118360efbdSAlfred Perlstein *
1128360efbdSAlfred Perlstein * The filedescriptor passed in is expected to refer to a bound, but
1138360efbdSAlfred Perlstein * not yet connected socket.
1148360efbdSAlfred Perlstein *
1158360efbdSAlfred Perlstein * Since streams do buffered io similar to stdio, the caller can specify
1168360efbdSAlfred Perlstein * how big the send and receive buffers are via the second and third parms;
1178360efbdSAlfred Perlstein * 0 => use the system default.
1188360efbdSAlfred Perlstein */
1198360efbdSAlfred Perlstein SVCXPRT *
svc_vc_create(int fd,u_int sendsize,u_int recvsize)12068895e38SCraig Rodrigues svc_vc_create(int fd, u_int sendsize, u_int recvsize)
1218360efbdSAlfred Perlstein {
122e742fdffSPedro F. Giffuni SVCXPRT *xprt = NULL;
1238360efbdSAlfred Perlstein struct cf_rendezvous *r = NULL;
1248360efbdSAlfred Perlstein struct __rpc_sockinfo si;
1258360efbdSAlfred Perlstein struct sockaddr_storage sslocal;
1268360efbdSAlfred Perlstein socklen_t slen;
1278360efbdSAlfred Perlstein
128794295baSMartin Blapp if (!__rpc_fd2sockinfo(fd, &si))
129794295baSMartin Blapp return NULL;
130794295baSMartin Blapp
1318360efbdSAlfred Perlstein r = mem_alloc(sizeof(*r));
1328360efbdSAlfred Perlstein if (r == NULL) {
1338360efbdSAlfred Perlstein warnx("svc_vc_create: out of memory");
1348360efbdSAlfred Perlstein goto cleanup_svc_vc_create;
1358360efbdSAlfred Perlstein }
1368360efbdSAlfred Perlstein r->sendsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsize);
1378360efbdSAlfred Perlstein r->recvsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsize);
13808497c02SMartin Blapp r->maxrec = __svc_maxrec;
1398f55a568SDoug Rabson xprt = svc_xprt_alloc();
1408360efbdSAlfred Perlstein if (xprt == NULL) {
1418360efbdSAlfred Perlstein warnx("svc_vc_create: out of memory");
1428360efbdSAlfred Perlstein goto cleanup_svc_vc_create;
1438360efbdSAlfred Perlstein }
144f249dbccSDag-Erling Smørgrav xprt->xp_p1 = r;
1458360efbdSAlfred Perlstein xprt->xp_verf = _null_auth;
1468360efbdSAlfred Perlstein svc_vc_rendezvous_ops(xprt);
1478360efbdSAlfred Perlstein xprt->xp_port = (u_short)-1; /* It is the rendezvouser */
1488360efbdSAlfred Perlstein xprt->xp_fd = fd;
1498360efbdSAlfred Perlstein
1508360efbdSAlfred Perlstein slen = sizeof (struct sockaddr_storage);
1518360efbdSAlfred Perlstein if (_getsockname(fd, (struct sockaddr *)(void *)&sslocal, &slen) < 0) {
1528360efbdSAlfred Perlstein warnx("svc_vc_create: could not retrieve local addr");
1538360efbdSAlfred Perlstein goto cleanup_svc_vc_create;
1548360efbdSAlfred Perlstein }
1558360efbdSAlfred Perlstein
1568360efbdSAlfred Perlstein xprt->xp_ltaddr.maxlen = xprt->xp_ltaddr.len = sslocal.ss_len;
1578360efbdSAlfred Perlstein xprt->xp_ltaddr.buf = mem_alloc((size_t)sslocal.ss_len);
1588360efbdSAlfred Perlstein if (xprt->xp_ltaddr.buf == NULL) {
1598360efbdSAlfred Perlstein warnx("svc_vc_create: no mem for local addr");
1608360efbdSAlfred Perlstein goto cleanup_svc_vc_create;
1618360efbdSAlfred Perlstein }
1628360efbdSAlfred Perlstein memcpy(xprt->xp_ltaddr.buf, &sslocal, (size_t)sslocal.ss_len);
1638360efbdSAlfred Perlstein
1648360efbdSAlfred Perlstein xprt->xp_rtaddr.maxlen = sizeof (struct sockaddr_storage);
1658360efbdSAlfred Perlstein xprt_register(xprt);
1668360efbdSAlfred Perlstein return (xprt);
1678360efbdSAlfred Perlstein cleanup_svc_vc_create:
168794295baSMartin Blapp if (xprt)
169794295baSMartin Blapp mem_free(xprt, sizeof(*xprt));
1708360efbdSAlfred Perlstein if (r != NULL)
1718360efbdSAlfred Perlstein mem_free(r, sizeof(*r));
1728360efbdSAlfred Perlstein return (NULL);
1738360efbdSAlfred Perlstein }
1748360efbdSAlfred Perlstein
1758360efbdSAlfred Perlstein /*
1768360efbdSAlfred Perlstein * Like svtcp_create(), except the routine takes any *open* UNIX file
1778360efbdSAlfred Perlstein * descriptor as its first input.
1788360efbdSAlfred Perlstein */
1798360efbdSAlfred Perlstein SVCXPRT *
svc_fd_create(int fd,u_int sendsize,u_int recvsize)18068895e38SCraig Rodrigues svc_fd_create(int fd, u_int sendsize, u_int recvsize)
1818360efbdSAlfred Perlstein {
1828360efbdSAlfred Perlstein struct sockaddr_storage ss;
1838360efbdSAlfred Perlstein socklen_t slen;
1848360efbdSAlfred Perlstein SVCXPRT *ret;
1858360efbdSAlfred Perlstein
1868360efbdSAlfred Perlstein assert(fd != -1);
1878360efbdSAlfred Perlstein
1888360efbdSAlfred Perlstein ret = makefd_xprt(fd, sendsize, recvsize);
1898360efbdSAlfred Perlstein if (ret == NULL)
1908360efbdSAlfred Perlstein return NULL;
1918360efbdSAlfred Perlstein
1928360efbdSAlfred Perlstein slen = sizeof (struct sockaddr_storage);
1938360efbdSAlfred Perlstein if (_getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) {
1948360efbdSAlfred Perlstein warnx("svc_fd_create: could not retrieve local addr");
1958360efbdSAlfred Perlstein goto freedata;
1968360efbdSAlfred Perlstein }
1978360efbdSAlfred Perlstein ret->xp_ltaddr.maxlen = ret->xp_ltaddr.len = ss.ss_len;
1988360efbdSAlfred Perlstein ret->xp_ltaddr.buf = mem_alloc((size_t)ss.ss_len);
1998360efbdSAlfred Perlstein if (ret->xp_ltaddr.buf == NULL) {
2008360efbdSAlfred Perlstein warnx("svc_fd_create: no mem for local addr");
2018360efbdSAlfred Perlstein goto freedata;
2028360efbdSAlfred Perlstein }
2038360efbdSAlfred Perlstein memcpy(ret->xp_ltaddr.buf, &ss, (size_t)ss.ss_len);
2048360efbdSAlfred Perlstein
2058360efbdSAlfred Perlstein slen = sizeof (struct sockaddr_storage);
2068360efbdSAlfred Perlstein if (_getpeername(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) {
2078360efbdSAlfred Perlstein warnx("svc_fd_create: could not retrieve remote addr");
2088360efbdSAlfred Perlstein goto freedata;
2098360efbdSAlfred Perlstein }
2108360efbdSAlfred Perlstein ret->xp_rtaddr.maxlen = ret->xp_rtaddr.len = ss.ss_len;
2118360efbdSAlfred Perlstein ret->xp_rtaddr.buf = mem_alloc((size_t)ss.ss_len);
2128360efbdSAlfred Perlstein if (ret->xp_rtaddr.buf == NULL) {
2138360efbdSAlfred Perlstein warnx("svc_fd_create: no mem for local addr");
2148360efbdSAlfred Perlstein goto freedata;
2158360efbdSAlfred Perlstein }
2168360efbdSAlfred Perlstein memcpy(ret->xp_rtaddr.buf, &ss, (size_t)ss.ss_len);
2178360efbdSAlfred Perlstein #ifdef PORTMAP
2182abd9cf1SAlfred Perlstein if (ss.ss_family == AF_INET || ss.ss_family == AF_LOCAL) {
2198360efbdSAlfred Perlstein ret->xp_raddr = *(struct sockaddr_in *)ret->xp_rtaddr.buf;
2208360efbdSAlfred Perlstein ret->xp_addrlen = sizeof (struct sockaddr_in);
2218360efbdSAlfred Perlstein }
2228360efbdSAlfred Perlstein #endif /* PORTMAP */
2238360efbdSAlfred Perlstein
2248360efbdSAlfred Perlstein return ret;
2258360efbdSAlfred Perlstein
2268360efbdSAlfred Perlstein freedata:
2278360efbdSAlfred Perlstein if (ret->xp_ltaddr.buf != NULL)
2288360efbdSAlfred Perlstein mem_free(ret->xp_ltaddr.buf, rep->xp_ltaddr.maxlen);
2298360efbdSAlfred Perlstein
2308360efbdSAlfred Perlstein return NULL;
2318360efbdSAlfred Perlstein }
2328360efbdSAlfred Perlstein
2338360efbdSAlfred Perlstein static SVCXPRT *
makefd_xprt(int fd,u_int sendsize,u_int recvsize)23468895e38SCraig Rodrigues makefd_xprt(int fd, u_int sendsize, u_int recvsize)
2358360efbdSAlfred Perlstein {
2368360efbdSAlfred Perlstein SVCXPRT *xprt;
2378360efbdSAlfred Perlstein struct cf_conn *cd;
2388360efbdSAlfred Perlstein const char *netid;
2398360efbdSAlfred Perlstein struct __rpc_sockinfo si;
2408360efbdSAlfred Perlstein
2418360efbdSAlfred Perlstein assert(fd != -1);
2428360efbdSAlfred Perlstein
2438f55a568SDoug Rabson xprt = svc_xprt_alloc();
2448360efbdSAlfred Perlstein if (xprt == NULL) {
2458360efbdSAlfred Perlstein warnx("svc_vc: makefd_xprt: out of memory");
2468360efbdSAlfred Perlstein goto done;
2478360efbdSAlfred Perlstein }
2488360efbdSAlfred Perlstein cd = mem_alloc(sizeof(struct cf_conn));
2498360efbdSAlfred Perlstein if (cd == NULL) {
2508360efbdSAlfred Perlstein warnx("svc_tcp: makefd_xprt: out of memory");
2518f55a568SDoug Rabson svc_xprt_free(xprt);
2528360efbdSAlfred Perlstein xprt = NULL;
2538360efbdSAlfred Perlstein goto done;
2548360efbdSAlfred Perlstein }
2558360efbdSAlfred Perlstein cd->strm_stat = XPRT_IDLE;
2568360efbdSAlfred Perlstein xdrrec_create(&(cd->xdrs), sendsize, recvsize,
257f249dbccSDag-Erling Smørgrav xprt, read_vc, write_vc);
258f249dbccSDag-Erling Smørgrav xprt->xp_p1 = cd;
2598360efbdSAlfred Perlstein xprt->xp_verf.oa_base = cd->verf_body;
26032223c1bSPedro F. Giffuni svc_vc_ops(xprt); /* truly deals with calls */
2618360efbdSAlfred Perlstein xprt->xp_port = 0; /* this is a connection, not a rendezvouser */
2628360efbdSAlfred Perlstein xprt->xp_fd = fd;
2638360efbdSAlfred Perlstein if (__rpc_fd2sockinfo(fd, &si) && __rpc_sockinfo2netid(&si, &netid))
2648360efbdSAlfred Perlstein xprt->xp_netid = strdup(netid);
2658360efbdSAlfred Perlstein
2668360efbdSAlfred Perlstein xprt_register(xprt);
2678360efbdSAlfred Perlstein done:
2688360efbdSAlfred Perlstein return (xprt);
2698360efbdSAlfred Perlstein }
2708360efbdSAlfred Perlstein
2718360efbdSAlfred Perlstein /*ARGSUSED*/
2728360efbdSAlfred Perlstein static bool_t
rendezvous_request(SVCXPRT * xprt,struct rpc_msg * msg)27368895e38SCraig Rodrigues rendezvous_request(SVCXPRT *xprt, struct rpc_msg *msg)
2748360efbdSAlfred Perlstein {
27508497c02SMartin Blapp int sock, flags;
2768360efbdSAlfred Perlstein struct cf_rendezvous *r;
27708497c02SMartin Blapp struct cf_conn *cd;
2785eff94eeSStanislav Sedov struct sockaddr_storage addr, sslocal;
2795eff94eeSStanislav Sedov socklen_t len, slen;
2808360efbdSAlfred Perlstein struct __rpc_sockinfo si;
28108497c02SMartin Blapp SVCXPRT *newxprt;
28208497c02SMartin Blapp fd_set cleanfds;
2838360efbdSAlfred Perlstein
2848360efbdSAlfred Perlstein assert(xprt != NULL);
2858360efbdSAlfred Perlstein assert(msg != NULL);
2868360efbdSAlfred Perlstein
2878360efbdSAlfred Perlstein r = (struct cf_rendezvous *)xprt->xp_p1;
2888360efbdSAlfred Perlstein again:
2898360efbdSAlfred Perlstein len = sizeof addr;
2908360efbdSAlfred Perlstein if ((sock = _accept(xprt->xp_fd, (struct sockaddr *)(void *)&addr,
2918360efbdSAlfred Perlstein &len)) < 0) {
2928360efbdSAlfred Perlstein if (errno == EINTR)
2938360efbdSAlfred Perlstein goto again;
29408497c02SMartin Blapp /*
29508497c02SMartin Blapp * Clean out the most idle file descriptor when we're
29608497c02SMartin Blapp * running out.
29708497c02SMartin Blapp */
29808497c02SMartin Blapp if (errno == EMFILE || errno == ENFILE) {
29908497c02SMartin Blapp cleanfds = svc_fdset;
30008497c02SMartin Blapp __svc_clean_idle(&cleanfds, 0, FALSE);
30108497c02SMartin Blapp goto again;
30208497c02SMartin Blapp }
3038360efbdSAlfred Perlstein return (FALSE);
3048360efbdSAlfred Perlstein }
3058360efbdSAlfred Perlstein /*
3068360efbdSAlfred Perlstein * make a new transporter (re-uses xprt)
3078360efbdSAlfred Perlstein */
30808497c02SMartin Blapp newxprt = makefd_xprt(sock, r->sendsize, r->recvsize);
30908497c02SMartin Blapp newxprt->xp_rtaddr.buf = mem_alloc(len);
31008497c02SMartin Blapp if (newxprt->xp_rtaddr.buf == NULL)
3118360efbdSAlfred Perlstein return (FALSE);
31208497c02SMartin Blapp memcpy(newxprt->xp_rtaddr.buf, &addr, len);
31308497c02SMartin Blapp newxprt->xp_rtaddr.len = len;
3148360efbdSAlfred Perlstein #ifdef PORTMAP
315866e3c90SAlfred Perlstein if (addr.ss_family == AF_INET || addr.ss_family == AF_LOCAL) {
31608497c02SMartin Blapp newxprt->xp_raddr = *(struct sockaddr_in *)newxprt->xp_rtaddr.buf;
31708497c02SMartin Blapp newxprt->xp_addrlen = sizeof (struct sockaddr_in);
3188360efbdSAlfred Perlstein }
3198360efbdSAlfred Perlstein #endif /* PORTMAP */
3208360efbdSAlfred Perlstein if (__rpc_fd2sockinfo(sock, &si) && si.si_proto == IPPROTO_TCP) {
3218360efbdSAlfred Perlstein len = 1;
3228360efbdSAlfred Perlstein /* XXX fvdl - is this useful? */
3238360efbdSAlfred Perlstein _setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &len, sizeof (len));
3248360efbdSAlfred Perlstein }
32508497c02SMartin Blapp
32608497c02SMartin Blapp cd = (struct cf_conn *)newxprt->xp_p1;
32708497c02SMartin Blapp
32808497c02SMartin Blapp cd->recvsize = r->recvsize;
32908497c02SMartin Blapp cd->sendsize = r->sendsize;
33008497c02SMartin Blapp cd->maxrec = r->maxrec;
33108497c02SMartin Blapp
33208497c02SMartin Blapp if (cd->maxrec != 0) {
3330ae0e1eaSMartin Blapp flags = _fcntl(sock, F_GETFL, 0);
33408497c02SMartin Blapp if (flags == -1)
33508497c02SMartin Blapp return (FALSE);
3360ae0e1eaSMartin Blapp if (_fcntl(sock, F_SETFL, flags | O_NONBLOCK) == -1)
33708497c02SMartin Blapp return (FALSE);
33808497c02SMartin Blapp if (cd->recvsize > cd->maxrec)
33908497c02SMartin Blapp cd->recvsize = cd->maxrec;
34008497c02SMartin Blapp cd->nonblock = TRUE;
34108497c02SMartin Blapp __xdrrec_setnonblock(&cd->xdrs, cd->maxrec);
34208497c02SMartin Blapp } else
34308497c02SMartin Blapp cd->nonblock = FALSE;
3445eff94eeSStanislav Sedov slen = sizeof(struct sockaddr_storage);
3455eff94eeSStanislav Sedov if(_getsockname(sock, (struct sockaddr *)(void *)&sslocal, &slen) < 0) {
3465eff94eeSStanislav Sedov warnx("svc_vc_create: could not retrieve local addr");
3475eff94eeSStanislav Sedov newxprt->xp_ltaddr.maxlen = newxprt->xp_ltaddr.len = 0;
3485eff94eeSStanislav Sedov } else {
3495eff94eeSStanislav Sedov newxprt->xp_ltaddr.maxlen = newxprt->xp_ltaddr.len = sslocal.ss_len;
3505eff94eeSStanislav Sedov newxprt->xp_ltaddr.buf = mem_alloc((size_t)sslocal.ss_len);
3515eff94eeSStanislav Sedov if (newxprt->xp_ltaddr.buf == NULL) {
3525eff94eeSStanislav Sedov warnx("svc_vc_create: no mem for local addr");
3535eff94eeSStanislav Sedov newxprt->xp_ltaddr.maxlen = newxprt->xp_ltaddr.len = 0;
3545eff94eeSStanislav Sedov } else {
3555eff94eeSStanislav Sedov memcpy(newxprt->xp_ltaddr.buf, &sslocal, (size_t)sslocal.ss_len);
3565eff94eeSStanislav Sedov }
3575eff94eeSStanislav Sedov }
35808497c02SMartin Blapp
35908497c02SMartin Blapp gettimeofday(&cd->last_recv_time, NULL);
36008497c02SMartin Blapp
3618360efbdSAlfred Perlstein return (FALSE); /* there is never an rpc msg to be processed */
3628360efbdSAlfred Perlstein }
3638360efbdSAlfred Perlstein
3648360efbdSAlfred Perlstein /*ARGSUSED*/
3658360efbdSAlfred Perlstein static enum xprt_stat
rendezvous_stat(SVCXPRT * xprt)36668895e38SCraig Rodrigues rendezvous_stat(SVCXPRT *xprt)
3678360efbdSAlfred Perlstein {
3688360efbdSAlfred Perlstein
3698360efbdSAlfred Perlstein return (XPRT_IDLE);
3708360efbdSAlfred Perlstein }
3718360efbdSAlfred Perlstein
3728360efbdSAlfred Perlstein static void
svc_vc_destroy(SVCXPRT * xprt)37368895e38SCraig Rodrigues svc_vc_destroy(SVCXPRT *xprt)
3748360efbdSAlfred Perlstein {
37508497c02SMartin Blapp assert(xprt != NULL);
37608497c02SMartin Blapp
37708497c02SMartin Blapp xprt_unregister(xprt);
37808497c02SMartin Blapp __svc_vc_dodestroy(xprt);
37908497c02SMartin Blapp }
38008497c02SMartin Blapp
38108497c02SMartin Blapp static void
__svc_vc_dodestroy(SVCXPRT * xprt)38268895e38SCraig Rodrigues __svc_vc_dodestroy(SVCXPRT *xprt)
38308497c02SMartin Blapp {
3848360efbdSAlfred Perlstein struct cf_conn *cd;
3858360efbdSAlfred Perlstein struct cf_rendezvous *r;
3868360efbdSAlfred Perlstein
3878360efbdSAlfred Perlstein cd = (struct cf_conn *)xprt->xp_p1;
3888360efbdSAlfred Perlstein
3898360efbdSAlfred Perlstein if (xprt->xp_fd != RPC_ANYFD)
3908360efbdSAlfred Perlstein (void)_close(xprt->xp_fd);
3918360efbdSAlfred Perlstein if (xprt->xp_port != 0) {
3928360efbdSAlfred Perlstein /* a rendezvouser socket */
3938360efbdSAlfred Perlstein r = (struct cf_rendezvous *)xprt->xp_p1;
3948360efbdSAlfred Perlstein mem_free(r, sizeof (struct cf_rendezvous));
3958360efbdSAlfred Perlstein xprt->xp_port = 0;
3968360efbdSAlfred Perlstein } else {
3978360efbdSAlfred Perlstein /* an actual connection socket */
3988360efbdSAlfred Perlstein XDR_DESTROY(&(cd->xdrs));
3998360efbdSAlfred Perlstein mem_free(cd, sizeof(struct cf_conn));
4008360efbdSAlfred Perlstein }
4018360efbdSAlfred Perlstein if (xprt->xp_rtaddr.buf)
4028360efbdSAlfred Perlstein mem_free(xprt->xp_rtaddr.buf, xprt->xp_rtaddr.maxlen);
4038360efbdSAlfred Perlstein if (xprt->xp_ltaddr.buf)
4048360efbdSAlfred Perlstein mem_free(xprt->xp_ltaddr.buf, xprt->xp_ltaddr.maxlen);
4058360efbdSAlfred Perlstein free(xprt->xp_tp);
4068360efbdSAlfred Perlstein free(xprt->xp_netid);
4078f55a568SDoug Rabson svc_xprt_free(xprt);
4088360efbdSAlfred Perlstein }
4098360efbdSAlfred Perlstein
4108360efbdSAlfred Perlstein /*ARGSUSED*/
4118360efbdSAlfred Perlstein static bool_t
svc_vc_control(SVCXPRT * xprt,const u_int rq,void * in)41268895e38SCraig Rodrigues svc_vc_control(SVCXPRT *xprt, const u_int rq, void *in)
4138360efbdSAlfred Perlstein {
4148360efbdSAlfred Perlstein return (FALSE);
4158360efbdSAlfred Perlstein }
4168360efbdSAlfred Perlstein
41708497c02SMartin Blapp static bool_t
svc_vc_rendezvous_control(SVCXPRT * xprt,const u_int rq,void * in)41868895e38SCraig Rodrigues svc_vc_rendezvous_control(SVCXPRT *xprt, const u_int rq, void *in)
41908497c02SMartin Blapp {
42008497c02SMartin Blapp struct cf_rendezvous *cfp;
42108497c02SMartin Blapp
42208497c02SMartin Blapp cfp = (struct cf_rendezvous *)xprt->xp_p1;
42308497c02SMartin Blapp if (cfp == NULL)
42408497c02SMartin Blapp return (FALSE);
42508497c02SMartin Blapp switch (rq) {
42608497c02SMartin Blapp case SVCGET_CONNMAXREC:
42708497c02SMartin Blapp *(int *)in = cfp->maxrec;
42808497c02SMartin Blapp break;
42908497c02SMartin Blapp case SVCSET_CONNMAXREC:
43008497c02SMartin Blapp cfp->maxrec = *(int *)in;
43108497c02SMartin Blapp break;
43208497c02SMartin Blapp default:
43308497c02SMartin Blapp return (FALSE);
43408497c02SMartin Blapp }
43508497c02SMartin Blapp return (TRUE);
43608497c02SMartin Blapp }
43708497c02SMartin Blapp
4388360efbdSAlfred Perlstein /*
4398360efbdSAlfred Perlstein * reads data from the tcp or uip connection.
4408360efbdSAlfred Perlstein * any error is fatal and the connection is closed.
4418360efbdSAlfred Perlstein * (And a read of zero bytes is a half closed stream => error.)
4428360efbdSAlfred Perlstein * All read operations timeout after 35 seconds. A timeout is
4438360efbdSAlfred Perlstein * fatal for the connection.
4448360efbdSAlfred Perlstein */
4458360efbdSAlfred Perlstein static int
read_vc(void * xprtp,void * buf,int len)44668895e38SCraig Rodrigues read_vc(void *xprtp, void *buf, int len)
4478360efbdSAlfred Perlstein {
4488360efbdSAlfred Perlstein SVCXPRT *xprt;
4498360efbdSAlfred Perlstein int sock;
4508360efbdSAlfred Perlstein int milliseconds = 35 * 1000;
4518360efbdSAlfred Perlstein struct pollfd pollfd;
45208497c02SMartin Blapp struct cf_conn *cfp;
4538360efbdSAlfred Perlstein
454f249dbccSDag-Erling Smørgrav xprt = (SVCXPRT *)xprtp;
4558360efbdSAlfred Perlstein assert(xprt != NULL);
4568360efbdSAlfred Perlstein
4578360efbdSAlfred Perlstein sock = xprt->xp_fd;
4588360efbdSAlfred Perlstein
45908497c02SMartin Blapp cfp = (struct cf_conn *)xprt->xp_p1;
46008497c02SMartin Blapp
46108497c02SMartin Blapp if (cfp->nonblock) {
4620ae0e1eaSMartin Blapp len = _read(sock, buf, (size_t)len);
46308497c02SMartin Blapp if (len < 0) {
46408497c02SMartin Blapp if (errno == EAGAIN)
46508497c02SMartin Blapp len = 0;
46608497c02SMartin Blapp else
46708497c02SMartin Blapp goto fatal_err;
46808497c02SMartin Blapp }
46908497c02SMartin Blapp if (len != 0)
47008497c02SMartin Blapp gettimeofday(&cfp->last_recv_time, NULL);
47108497c02SMartin Blapp return len;
47208497c02SMartin Blapp }
47308497c02SMartin Blapp
4748360efbdSAlfred Perlstein do {
4758360efbdSAlfred Perlstein pollfd.fd = sock;
4768360efbdSAlfred Perlstein pollfd.events = POLLIN;
4778360efbdSAlfred Perlstein pollfd.revents = 0;
4788360efbdSAlfred Perlstein switch (_poll(&pollfd, 1, milliseconds)) {
4798360efbdSAlfred Perlstein case -1:
480fa87b7eaSAlfred Perlstein if (errno == EINTR)
4818360efbdSAlfred Perlstein continue;
4828360efbdSAlfred Perlstein /*FALLTHROUGH*/
4838360efbdSAlfred Perlstein case 0:
4848360efbdSAlfred Perlstein goto fatal_err;
4854ed6d634SAlfred Perlstein
4868360efbdSAlfred Perlstein default:
4878360efbdSAlfred Perlstein break;
4888360efbdSAlfred Perlstein }
4898360efbdSAlfred Perlstein } while ((pollfd.revents & POLLIN) == 0);
4908360efbdSAlfred Perlstein
4910ae0e1eaSMartin Blapp if ((len = _read(sock, buf, (size_t)len)) > 0) {
49208497c02SMartin Blapp gettimeofday(&cfp->last_recv_time, NULL);
4938360efbdSAlfred Perlstein return (len);
4948360efbdSAlfred Perlstein }
4958360efbdSAlfred Perlstein
4968360efbdSAlfred Perlstein fatal_err:
4978360efbdSAlfred Perlstein ((struct cf_conn *)(xprt->xp_p1))->strm_stat = XPRT_DIED;
4988360efbdSAlfred Perlstein return (-1);
4998360efbdSAlfred Perlstein }
5008360efbdSAlfred Perlstein
5018360efbdSAlfred Perlstein /*
5028360efbdSAlfred Perlstein * writes data to the tcp connection.
5038360efbdSAlfred Perlstein * Any error is fatal and the connection is closed.
5048360efbdSAlfred Perlstein */
5058360efbdSAlfred Perlstein static int
write_vc(void * xprtp,void * buf,int len)50668895e38SCraig Rodrigues write_vc(void *xprtp, void *buf, int len)
5078360efbdSAlfred Perlstein {
5088360efbdSAlfred Perlstein SVCXPRT *xprt;
5098360efbdSAlfred Perlstein int i, cnt;
51008497c02SMartin Blapp struct cf_conn *cd;
51108497c02SMartin Blapp struct timeval tv0, tv1;
5128360efbdSAlfred Perlstein
513f249dbccSDag-Erling Smørgrav xprt = (SVCXPRT *)xprtp;
5148360efbdSAlfred Perlstein assert(xprt != NULL);
5158360efbdSAlfred Perlstein
51608497c02SMartin Blapp cd = (struct cf_conn *)xprt->xp_p1;
51708497c02SMartin Blapp
51808497c02SMartin Blapp if (cd->nonblock)
51908497c02SMartin Blapp gettimeofday(&tv0, NULL);
52008497c02SMartin Blapp
521361de173SStefan Farfeleder for (cnt = len; cnt > 0; cnt -= i, buf = (char *)buf + i) {
52208497c02SMartin Blapp i = _write(xprt->xp_fd, buf, (size_t)cnt);
52308497c02SMartin Blapp if (i < 0) {
52408497c02SMartin Blapp if (errno != EAGAIN || !cd->nonblock) {
52508497c02SMartin Blapp cd->strm_stat = XPRT_DIED;
5268360efbdSAlfred Perlstein return (-1);
5278360efbdSAlfred Perlstein }
528e2c83f74SRick Macklem if (cd->nonblock) {
52908497c02SMartin Blapp /*
53008497c02SMartin Blapp * For non-blocking connections, do not
53108497c02SMartin Blapp * take more than 2 seconds writing the
53208497c02SMartin Blapp * data out.
53308497c02SMartin Blapp *
53408497c02SMartin Blapp * XXX 2 is an arbitrary amount.
53508497c02SMartin Blapp */
53608497c02SMartin Blapp gettimeofday(&tv1, NULL);
53708497c02SMartin Blapp if (tv1.tv_sec - tv0.tv_sec >= 2) {
53808497c02SMartin Blapp cd->strm_stat = XPRT_DIED;
5398360efbdSAlfred Perlstein return (-1);
5408360efbdSAlfred Perlstein }
5418360efbdSAlfred Perlstein }
542e2c83f74SRick Macklem i = 0;
5438360efbdSAlfred Perlstein }
54408497c02SMartin Blapp }
5458360efbdSAlfred Perlstein
5468360efbdSAlfred Perlstein return (len);
5478360efbdSAlfred Perlstein }
5488360efbdSAlfred Perlstein
5498360efbdSAlfred Perlstein static enum xprt_stat
svc_vc_stat(SVCXPRT * xprt)55068895e38SCraig Rodrigues svc_vc_stat(SVCXPRT *xprt)
5518360efbdSAlfred Perlstein {
5528360efbdSAlfred Perlstein struct cf_conn *cd;
5538360efbdSAlfred Perlstein
5548360efbdSAlfred Perlstein assert(xprt != NULL);
5558360efbdSAlfred Perlstein
5568360efbdSAlfred Perlstein cd = (struct cf_conn *)(xprt->xp_p1);
5578360efbdSAlfred Perlstein
5588360efbdSAlfred Perlstein if (cd->strm_stat == XPRT_DIED)
5598360efbdSAlfred Perlstein return (XPRT_DIED);
5608360efbdSAlfred Perlstein if (! xdrrec_eof(&(cd->xdrs)))
5618360efbdSAlfred Perlstein return (XPRT_MOREREQS);
5628360efbdSAlfred Perlstein return (XPRT_IDLE);
5638360efbdSAlfred Perlstein }
5648360efbdSAlfred Perlstein
5658360efbdSAlfred Perlstein static bool_t
svc_vc_recv(SVCXPRT * xprt,struct rpc_msg * msg)56668895e38SCraig Rodrigues svc_vc_recv(SVCXPRT *xprt, struct rpc_msg *msg)
5678360efbdSAlfred Perlstein {
5688360efbdSAlfred Perlstein struct cf_conn *cd;
5698360efbdSAlfred Perlstein XDR *xdrs;
5708360efbdSAlfred Perlstein
5718360efbdSAlfred Perlstein assert(xprt != NULL);
5728360efbdSAlfred Perlstein assert(msg != NULL);
5738360efbdSAlfred Perlstein
5748360efbdSAlfred Perlstein cd = (struct cf_conn *)(xprt->xp_p1);
5758360efbdSAlfred Perlstein xdrs = &(cd->xdrs);
5768360efbdSAlfred Perlstein
57708497c02SMartin Blapp if (cd->nonblock) {
57808497c02SMartin Blapp if (!__xdrrec_getrec(xdrs, &cd->strm_stat, TRUE))
57908497c02SMartin Blapp return FALSE;
580ecc03b80SDoug Rabson } else {
581ecc03b80SDoug Rabson (void)xdrrec_skiprecord(xdrs);
58208497c02SMartin Blapp }
58308497c02SMartin Blapp
5848360efbdSAlfred Perlstein xdrs->x_op = XDR_DECODE;
5858360efbdSAlfred Perlstein if (xdr_callmsg(xdrs, msg)) {
5868360efbdSAlfred Perlstein cd->x_id = msg->rm_xid;
5878360efbdSAlfred Perlstein return (TRUE);
5888360efbdSAlfred Perlstein }
5898360efbdSAlfred Perlstein cd->strm_stat = XPRT_DIED;
5908360efbdSAlfred Perlstein return (FALSE);
5918360efbdSAlfred Perlstein }
5928360efbdSAlfred Perlstein
5938360efbdSAlfred Perlstein static bool_t
svc_vc_getargs(SVCXPRT * xprt,xdrproc_t xdr_args,void * args_ptr)59468895e38SCraig Rodrigues svc_vc_getargs(SVCXPRT *xprt, xdrproc_t xdr_args, void *args_ptr)
5958360efbdSAlfred Perlstein {
5968f55a568SDoug Rabson struct cf_conn *cd;
5978360efbdSAlfred Perlstein
5988360efbdSAlfred Perlstein assert(xprt != NULL);
5998f55a568SDoug Rabson cd = (struct cf_conn *)(xprt->xp_p1);
6008f55a568SDoug Rabson return (SVCAUTH_UNWRAP(&SVC_AUTH(xprt),
6018f55a568SDoug Rabson &cd->xdrs, xdr_args, args_ptr));
6028360efbdSAlfred Perlstein }
6038360efbdSAlfred Perlstein
6048360efbdSAlfred Perlstein static bool_t
svc_vc_freeargs(SVCXPRT * xprt,xdrproc_t xdr_args,void * args_ptr)60568895e38SCraig Rodrigues svc_vc_freeargs(SVCXPRT *xprt, xdrproc_t xdr_args, void *args_ptr)
6068360efbdSAlfred Perlstein {
6078360efbdSAlfred Perlstein XDR *xdrs;
6088360efbdSAlfred Perlstein
6098360efbdSAlfred Perlstein assert(xprt != NULL);
6108360efbdSAlfred Perlstein /* args_ptr may be NULL */
6118360efbdSAlfred Perlstein
6128360efbdSAlfred Perlstein xdrs = &(((struct cf_conn *)(xprt->xp_p1))->xdrs);
6138360efbdSAlfred Perlstein
6148360efbdSAlfred Perlstein xdrs->x_op = XDR_FREE;
6158360efbdSAlfred Perlstein return ((*xdr_args)(xdrs, args_ptr));
6168360efbdSAlfred Perlstein }
6178360efbdSAlfred Perlstein
6188360efbdSAlfred Perlstein static bool_t
svc_vc_reply(SVCXPRT * xprt,struct rpc_msg * msg)61968895e38SCraig Rodrigues svc_vc_reply(SVCXPRT *xprt, struct rpc_msg *msg)
6208360efbdSAlfred Perlstein {
6218360efbdSAlfred Perlstein struct cf_conn *cd;
6228360efbdSAlfred Perlstein XDR *xdrs;
62308497c02SMartin Blapp bool_t rstat;
6248f55a568SDoug Rabson xdrproc_t xdr_proc;
6258f55a568SDoug Rabson caddr_t xdr_where;
6268f55a568SDoug Rabson u_int pos;
6278360efbdSAlfred Perlstein
6288360efbdSAlfred Perlstein assert(xprt != NULL);
6298360efbdSAlfred Perlstein assert(msg != NULL);
6308360efbdSAlfred Perlstein
6318360efbdSAlfred Perlstein cd = (struct cf_conn *)(xprt->xp_p1);
6328360efbdSAlfred Perlstein xdrs = &(cd->xdrs);
6338360efbdSAlfred Perlstein
6348360efbdSAlfred Perlstein xdrs->x_op = XDR_ENCODE;
6358360efbdSAlfred Perlstein msg->rm_xid = cd->x_id;
6368f55a568SDoug Rabson rstat = TRUE;
6378f55a568SDoug Rabson if (msg->rm_reply.rp_stat == MSG_ACCEPTED &&
6388f55a568SDoug Rabson msg->rm_reply.rp_acpt.ar_stat == SUCCESS) {
6398f55a568SDoug Rabson xdr_proc = msg->acpted_rply.ar_results.proc;
6408f55a568SDoug Rabson xdr_where = msg->acpted_rply.ar_results.where;
6418f55a568SDoug Rabson msg->acpted_rply.ar_results.proc = (xdrproc_t) xdr_void;
6428f55a568SDoug Rabson msg->acpted_rply.ar_results.where = NULL;
6438f55a568SDoug Rabson
6448f55a568SDoug Rabson pos = XDR_GETPOS(xdrs);
6458f55a568SDoug Rabson if (!xdr_replymsg(xdrs, msg) ||
6468f55a568SDoug Rabson !SVCAUTH_WRAP(&SVC_AUTH(xprt), xdrs, xdr_proc, xdr_where)) {
6478f55a568SDoug Rabson XDR_SETPOS(xdrs, pos);
6488f55a568SDoug Rabson rstat = FALSE;
6498f55a568SDoug Rabson }
6508f55a568SDoug Rabson } else {
65108497c02SMartin Blapp rstat = xdr_replymsg(xdrs, msg);
6528f55a568SDoug Rabson }
6538f55a568SDoug Rabson
6548f55a568SDoug Rabson if (rstat)
6558360efbdSAlfred Perlstein (void)xdrrec_endofrecord(xdrs, TRUE);
6568f55a568SDoug Rabson
65708497c02SMartin Blapp return (rstat);
6588360efbdSAlfred Perlstein }
6598360efbdSAlfred Perlstein
6608360efbdSAlfred Perlstein static void
svc_vc_ops(SVCXPRT * xprt)66168895e38SCraig Rodrigues svc_vc_ops(SVCXPRT *xprt)
6628360efbdSAlfred Perlstein {
6638360efbdSAlfred Perlstein static struct xp_ops ops;
6648360efbdSAlfred Perlstein static struct xp_ops2 ops2;
6658360efbdSAlfred Perlstein
6668360efbdSAlfred Perlstein /* VARIABLES PROTECTED BY ops_lock: ops, ops2 */
6678360efbdSAlfred Perlstein
6688360efbdSAlfred Perlstein mutex_lock(&ops_lock);
6698360efbdSAlfred Perlstein if (ops.xp_recv == NULL) {
6708360efbdSAlfred Perlstein ops.xp_recv = svc_vc_recv;
6718360efbdSAlfred Perlstein ops.xp_stat = svc_vc_stat;
6728360efbdSAlfred Perlstein ops.xp_getargs = svc_vc_getargs;
6738360efbdSAlfred Perlstein ops.xp_reply = svc_vc_reply;
6748360efbdSAlfred Perlstein ops.xp_freeargs = svc_vc_freeargs;
6758360efbdSAlfred Perlstein ops.xp_destroy = svc_vc_destroy;
6768360efbdSAlfred Perlstein ops2.xp_control = svc_vc_control;
6778360efbdSAlfred Perlstein }
6788360efbdSAlfred Perlstein xprt->xp_ops = &ops;
6798360efbdSAlfred Perlstein xprt->xp_ops2 = &ops2;
6808360efbdSAlfred Perlstein mutex_unlock(&ops_lock);
6818360efbdSAlfred Perlstein }
6828360efbdSAlfred Perlstein
6838360efbdSAlfred Perlstein static void
svc_vc_rendezvous_ops(SVCXPRT * xprt)68468895e38SCraig Rodrigues svc_vc_rendezvous_ops(SVCXPRT *xprt)
6858360efbdSAlfred Perlstein {
6868360efbdSAlfred Perlstein static struct xp_ops ops;
6878360efbdSAlfred Perlstein static struct xp_ops2 ops2;
6888360efbdSAlfred Perlstein
6898360efbdSAlfred Perlstein mutex_lock(&ops_lock);
6908360efbdSAlfred Perlstein if (ops.xp_recv == NULL) {
6918360efbdSAlfred Perlstein ops.xp_recv = rendezvous_request;
6928360efbdSAlfred Perlstein ops.xp_stat = rendezvous_stat;
6938360efbdSAlfred Perlstein ops.xp_getargs =
694f249dbccSDag-Erling Smørgrav (bool_t (*)(SVCXPRT *, xdrproc_t, void *))abort;
6958360efbdSAlfred Perlstein ops.xp_reply =
6961372519bSDavid E. O'Brien (bool_t (*)(SVCXPRT *, struct rpc_msg *))abort;
6978360efbdSAlfred Perlstein ops.xp_freeargs =
6988e60fa95SPedro F. Giffuni (bool_t (*)(SVCXPRT *, xdrproc_t, void *))abort;
6998360efbdSAlfred Perlstein ops.xp_destroy = svc_vc_destroy;
70008497c02SMartin Blapp ops2.xp_control = svc_vc_rendezvous_control;
7018360efbdSAlfred Perlstein }
7028360efbdSAlfred Perlstein xprt->xp_ops = &ops;
7038360efbdSAlfred Perlstein xprt->xp_ops2 = &ops2;
7048360efbdSAlfred Perlstein mutex_unlock(&ops_lock);
7058360efbdSAlfred Perlstein }
7068360efbdSAlfred Perlstein
7074ed6d634SAlfred Perlstein /*
708ce9bc43cSMartin Blapp * Get the effective UID of the sending process. Used by rpcbind, keyserv
709ce9bc43cSMartin Blapp * and rpc.yppasswdd on AF_LOCAL.
7104ed6d634SAlfred Perlstein */
7114ed6d634SAlfred Perlstein int
__rpc_get_local_uid(SVCXPRT * transp,uid_t * uid)712ce9bc43cSMartin Blapp __rpc_get_local_uid(SVCXPRT *transp, uid_t *uid) {
713ce9bc43cSMartin Blapp int sock, ret;
714ce9bc43cSMartin Blapp gid_t egid;
715ce9bc43cSMartin Blapp uid_t euid;
716ce9bc43cSMartin Blapp struct sockaddr *sa;
71708760d5aSAlfred Perlstein
718ce9bc43cSMartin Blapp sock = transp->xp_fd;
719ce9bc43cSMartin Blapp sa = (struct sockaddr *)transp->xp_rtaddr.buf;
720ce9bc43cSMartin Blapp if (sa->sa_family == AF_LOCAL) {
721ce9bc43cSMartin Blapp ret = getpeereid(sock, &euid, &egid);
722ce9bc43cSMartin Blapp if (ret == 0)
723ce9bc43cSMartin Blapp *uid = euid;
724ce9bc43cSMartin Blapp return (ret);
725ce9bc43cSMartin Blapp } else
72608760d5aSAlfred Perlstein return (-1);
7274ed6d634SAlfred Perlstein }
72808497c02SMartin Blapp
72908497c02SMartin Blapp /*
73008497c02SMartin Blapp * Destroy xprts that have not have had any activity in 'timeout' seconds.
73108497c02SMartin Blapp * If 'cleanblock' is true, blocking connections (the default) are also
73208497c02SMartin Blapp * cleaned. If timeout is 0, the least active connection is picked.
73308497c02SMartin Blapp */
73408497c02SMartin Blapp bool_t
__svc_clean_idle(fd_set * fds,int timeout,bool_t cleanblock)73508497c02SMartin Blapp __svc_clean_idle(fd_set *fds, int timeout, bool_t cleanblock)
73608497c02SMartin Blapp {
73708497c02SMartin Blapp int i, ncleaned;
73808497c02SMartin Blapp SVCXPRT *xprt, *least_active;
73908497c02SMartin Blapp struct timeval tv, tdiff, tmax;
74008497c02SMartin Blapp struct cf_conn *cd;
74108497c02SMartin Blapp
74208497c02SMartin Blapp gettimeofday(&tv, NULL);
74308497c02SMartin Blapp tmax.tv_sec = tmax.tv_usec = 0;
74408497c02SMartin Blapp least_active = NULL;
74508497c02SMartin Blapp rwlock_wrlock(&svc_fd_lock);
74608497c02SMartin Blapp for (i = ncleaned = 0; i <= svc_maxfd; i++) {
74708497c02SMartin Blapp if (FD_ISSET(i, fds)) {
74808497c02SMartin Blapp xprt = __svc_xports[i];
74908497c02SMartin Blapp if (xprt == NULL || xprt->xp_ops == NULL ||
75008497c02SMartin Blapp xprt->xp_ops->xp_recv != svc_vc_recv)
75108497c02SMartin Blapp continue;
75208497c02SMartin Blapp cd = (struct cf_conn *)xprt->xp_p1;
75308497c02SMartin Blapp if (!cleanblock && !cd->nonblock)
75408497c02SMartin Blapp continue;
75508497c02SMartin Blapp if (timeout == 0) {
75608497c02SMartin Blapp timersub(&tv, &cd->last_recv_time, &tdiff);
75708497c02SMartin Blapp if (timercmp(&tdiff, &tmax, >)) {
75808497c02SMartin Blapp tmax = tdiff;
75908497c02SMartin Blapp least_active = xprt;
76008497c02SMartin Blapp }
76108497c02SMartin Blapp continue;
76208497c02SMartin Blapp }
76308497c02SMartin Blapp if (tv.tv_sec - cd->last_recv_time.tv_sec > timeout) {
76408497c02SMartin Blapp __xprt_unregister_unlocked(xprt);
76508497c02SMartin Blapp __svc_vc_dodestroy(xprt);
76608497c02SMartin Blapp ncleaned++;
76708497c02SMartin Blapp }
76808497c02SMartin Blapp }
76908497c02SMartin Blapp }
77008497c02SMartin Blapp if (timeout == 0 && least_active != NULL) {
77108497c02SMartin Blapp __xprt_unregister_unlocked(least_active);
77208497c02SMartin Blapp __svc_vc_dodestroy(least_active);
77308497c02SMartin Blapp ncleaned++;
77408497c02SMartin Blapp }
77508497c02SMartin Blapp rwlock_unlock(&svc_fd_lock);
77608497c02SMartin Blapp return ncleaned > 0 ? TRUE : FALSE;
77708497c02SMartin Blapp }
778