1ba96d07fShrs /*-
2ba96d07fShrs * Copyright (c) 2009, Sun Microsystems, Inc.
3ba96d07fShrs * All rights reserved.
4ce0e08e2SPeter Avalos *
5ba96d07fShrs * Redistribution and use in source and binary forms, with or without
6ba96d07fShrs * modification, are permitted provided that the following conditions are met:
7ba96d07fShrs * - Redistributions of source code must retain the above copyright notice,
8ba96d07fShrs * this list of conditions and the following disclaimer.
9ba96d07fShrs * - Redistributions in binary form must reproduce the above copyright notice,
10ba96d07fShrs * this list of conditions and the following disclaimer in the documentation
11ba96d07fShrs * and/or other materials provided with the distribution.
12ba96d07fShrs * - Neither the name of Sun Microsystems, Inc. nor the names of its
13ba96d07fShrs * contributors may be used to endorse or promote products derived
14ba96d07fShrs * from this software without specific prior written permission.
15ce0e08e2SPeter Avalos *
16ba96d07fShrs * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17ba96d07fShrs * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18ba96d07fShrs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19ba96d07fShrs * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20ba96d07fShrs * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21ba96d07fShrs * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22ba96d07fShrs * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23ba96d07fShrs * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24ba96d07fShrs * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25ba96d07fShrs * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26ba96d07fShrs * POSSIBILITY OF SUCH DAMAGE.
27ce0e08e2SPeter Avalos *
28ce0e08e2SPeter Avalos * @(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro
29ce0e08e2SPeter Avalos * @(#)svc_tcp.c 2.2 88/08/01 4.0 RPCSRC
30ce0e08e2SPeter Avalos * $NetBSD: svc_vc.c,v 1.7 2000/08/03 00:01:53 fvdl Exp $
31ce0e08e2SPeter Avalos * $FreeBSD: src/lib/libc/rpc/svc_vc.c,v 1.27 2008/03/30 09:36:17 dfr Exp $
32ce0e08e2SPeter Avalos */
33ce0e08e2SPeter Avalos
34ce0e08e2SPeter Avalos /*
35ce0e08e2SPeter Avalos * svc_vc.c, Server side for Connection Oriented based RPC.
36ce0e08e2SPeter Avalos *
37ce0e08e2SPeter Avalos * Actually implements two flavors of transporter -
38ce0e08e2SPeter Avalos * a tcp rendezvouser (a listner and connection establisher)
39ce0e08e2SPeter Avalos * and a record/tcp stream.
40ce0e08e2SPeter Avalos */
41ce0e08e2SPeter Avalos
42ce0e08e2SPeter Avalos #include "namespace.h"
43ce0e08e2SPeter Avalos #include "reentrant.h"
44ce0e08e2SPeter Avalos #include <sys/types.h>
45ce0e08e2SPeter Avalos #include <sys/param.h>
46ce0e08e2SPeter Avalos #include <sys/poll.h>
47ce0e08e2SPeter Avalos #include <sys/socket.h>
48ce0e08e2SPeter Avalos #include <sys/un.h>
49ce0e08e2SPeter Avalos #include <sys/time.h>
50ce0e08e2SPeter Avalos #include <sys/uio.h>
51ce0e08e2SPeter Avalos #include <netinet/in.h>
52ce0e08e2SPeter Avalos #include <netinet/tcp.h>
53ce0e08e2SPeter Avalos
54ce0e08e2SPeter Avalos #include <assert.h>
55ce0e08e2SPeter Avalos #include <err.h>
56ce0e08e2SPeter Avalos #include <errno.h>
57ce0e08e2SPeter Avalos #include <fcntl.h>
58ce0e08e2SPeter Avalos #include <stdio.h>
59ce0e08e2SPeter Avalos #include <stdlib.h>
60ce0e08e2SPeter Avalos #include <string.h>
61ce0e08e2SPeter Avalos #include <unistd.h>
62ce0e08e2SPeter Avalos
63ce0e08e2SPeter Avalos #include <rpc/rpc.h>
64ce0e08e2SPeter Avalos
65ce0e08e2SPeter Avalos #include "rpc_com.h"
66ce0e08e2SPeter Avalos #include "mt_misc.h"
67ce0e08e2SPeter Avalos #include "un-namespace.h"
68ce0e08e2SPeter Avalos
69ce0e08e2SPeter Avalos static SVCXPRT *makefd_xprt(int, u_int, u_int);
70ce0e08e2SPeter Avalos static bool_t rendezvous_request(SVCXPRT *, struct rpc_msg *);
71ce0e08e2SPeter Avalos static enum xprt_stat rendezvous_stat(SVCXPRT *);
72ce0e08e2SPeter Avalos static void svc_vc_destroy(SVCXPRT *);
73ce0e08e2SPeter Avalos static void __svc_vc_dodestroy (SVCXPRT *);
74ce0e08e2SPeter Avalos static int read_vc(void *, void *, int);
75ce0e08e2SPeter Avalos static int write_vc(void *, void *, int);
76ce0e08e2SPeter Avalos static enum xprt_stat svc_vc_stat(SVCXPRT *);
77ce0e08e2SPeter Avalos static bool_t svc_vc_recv(SVCXPRT *, struct rpc_msg *);
78ce0e08e2SPeter Avalos static bool_t svc_vc_getargs(SVCXPRT *, xdrproc_t, void *);
79ce0e08e2SPeter Avalos static bool_t svc_vc_freeargs(SVCXPRT *, xdrproc_t, void *);
80ce0e08e2SPeter Avalos static bool_t svc_vc_reply(SVCXPRT *, struct rpc_msg *);
81ce0e08e2SPeter Avalos static void svc_vc_rendezvous_ops(SVCXPRT *);
82ce0e08e2SPeter Avalos static void svc_vc_ops(SVCXPRT *);
83ce0e08e2SPeter Avalos static bool_t svc_vc_control(SVCXPRT *xprt, const u_int rq, void *in);
84ce0e08e2SPeter Avalos static bool_t svc_vc_rendezvous_control(SVCXPRT *xprt, const u_int rq,
85ce0e08e2SPeter Avalos void *in);
86ce0e08e2SPeter Avalos
87ce0e08e2SPeter Avalos struct cf_rendezvous { /* kept in xprt->xp_p1 for rendezvouser */
88ce0e08e2SPeter Avalos u_int sendsize;
89ce0e08e2SPeter Avalos u_int recvsize;
90ce0e08e2SPeter Avalos int maxrec;
91ce0e08e2SPeter Avalos };
92ce0e08e2SPeter Avalos
93ce0e08e2SPeter Avalos struct cf_conn { /* kept in xprt->xp_p1 for actual connection */
94ce0e08e2SPeter Avalos enum xprt_stat strm_stat;
95ce0e08e2SPeter Avalos u_int32_t x_id;
96ce0e08e2SPeter Avalos XDR xdrs;
97ce0e08e2SPeter Avalos char verf_body[MAX_AUTH_BYTES];
98ce0e08e2SPeter Avalos u_int sendsize;
99ce0e08e2SPeter Avalos u_int recvsize;
100ce0e08e2SPeter Avalos int maxrec;
101ce0e08e2SPeter Avalos bool_t nonblock;
102ce0e08e2SPeter Avalos struct timeval last_recv_time;
103ce0e08e2SPeter Avalos };
104ce0e08e2SPeter Avalos
105ce0e08e2SPeter Avalos /*
106ce0e08e2SPeter Avalos * Usage:
107ce0e08e2SPeter Avalos * xprt = svc_vc_create(sock, send_buf_size, recv_buf_size);
108ce0e08e2SPeter Avalos *
109ce0e08e2SPeter Avalos * Creates, registers, and returns a (rpc) tcp based transporter.
110ce0e08e2SPeter Avalos * Once *xprt is initialized, it is registered as a transporter
111ce0e08e2SPeter Avalos * see (svc.h, xprt_register). This routine returns
112ce0e08e2SPeter Avalos * a NULL if a problem occurred.
113ce0e08e2SPeter Avalos *
114ce0e08e2SPeter Avalos * The filedescriptor passed in is expected to refer to a bound, but
115ce0e08e2SPeter Avalos * not yet connected socket.
116ce0e08e2SPeter Avalos *
117ce0e08e2SPeter Avalos * Since streams do buffered io similar to stdio, the caller can specify
118ce0e08e2SPeter Avalos * how big the send and receive buffers are via the second and third parms;
119ce0e08e2SPeter Avalos * 0 => use the system default.
120ce0e08e2SPeter Avalos */
121ce0e08e2SPeter Avalos SVCXPRT *
svc_vc_create(int fd,u_int sendsize,u_int recvsize)122ce0e08e2SPeter Avalos svc_vc_create(int fd, u_int sendsize, u_int recvsize)
123ce0e08e2SPeter Avalos {
124e5154c07SSascha Wildner SVCXPRT *xprt = NULL;
125ce0e08e2SPeter Avalos struct cf_rendezvous *r = NULL;
126ce0e08e2SPeter Avalos struct __rpc_sockinfo si;
127ce0e08e2SPeter Avalos struct sockaddr_storage sslocal;
128ce0e08e2SPeter Avalos socklen_t slen;
129ce0e08e2SPeter Avalos
130ce0e08e2SPeter Avalos if (!__rpc_fd2sockinfo(fd, &si))
131ce0e08e2SPeter Avalos return NULL;
132ce0e08e2SPeter Avalos
133ce0e08e2SPeter Avalos r = mem_alloc(sizeof(*r));
134ce0e08e2SPeter Avalos if (r == NULL) {
135ce0e08e2SPeter Avalos warnx("svc_vc_create: out of memory");
136ce0e08e2SPeter Avalos goto cleanup_svc_vc_create;
137ce0e08e2SPeter Avalos }
138ce0e08e2SPeter Avalos r->sendsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsize);
139ce0e08e2SPeter Avalos r->recvsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsize);
140ce0e08e2SPeter Avalos r->maxrec = __svc_maxrec;
141ce0e08e2SPeter Avalos xprt = mem_alloc(sizeof(SVCXPRT));
142ce0e08e2SPeter Avalos if (xprt == NULL) {
143ce0e08e2SPeter Avalos warnx("svc_vc_create: out of memory");
144ce0e08e2SPeter Avalos goto cleanup_svc_vc_create;
145ce0e08e2SPeter Avalos }
146ce0e08e2SPeter Avalos xprt->xp_tp = NULL;
147ce0e08e2SPeter Avalos xprt->xp_p1 = r;
148ce0e08e2SPeter Avalos xprt->xp_p2 = NULL;
149ce0e08e2SPeter Avalos xprt->xp_p3 = NULL;
150ce0e08e2SPeter Avalos xprt->xp_verf = _null_auth;
151ce0e08e2SPeter Avalos svc_vc_rendezvous_ops(xprt);
152ce0e08e2SPeter Avalos xprt->xp_port = (u_short)-1; /* It is the rendezvouser */
153ce0e08e2SPeter Avalos xprt->xp_fd = fd;
154ce0e08e2SPeter Avalos
155ce0e08e2SPeter Avalos slen = sizeof (struct sockaddr_storage);
156ce0e08e2SPeter Avalos if (_getsockname(fd, (struct sockaddr *)(void *)&sslocal, &slen) < 0) {
157ce0e08e2SPeter Avalos warnx("svc_vc_create: could not retrieve local addr");
158ce0e08e2SPeter Avalos goto cleanup_svc_vc_create;
159ce0e08e2SPeter Avalos }
160ce0e08e2SPeter Avalos
161ce0e08e2SPeter Avalos xprt->xp_ltaddr.maxlen = xprt->xp_ltaddr.len = sslocal.ss_len;
162ce0e08e2SPeter Avalos xprt->xp_ltaddr.buf = mem_alloc((size_t)sslocal.ss_len);
163ce0e08e2SPeter Avalos if (xprt->xp_ltaddr.buf == NULL) {
164ce0e08e2SPeter Avalos warnx("svc_vc_create: no mem for local addr");
165ce0e08e2SPeter Avalos goto cleanup_svc_vc_create;
166ce0e08e2SPeter Avalos }
167ce0e08e2SPeter Avalos memcpy(xprt->xp_ltaddr.buf, &sslocal, (size_t)sslocal.ss_len);
168ce0e08e2SPeter Avalos
169ce0e08e2SPeter Avalos xprt->xp_rtaddr.maxlen = sizeof (struct sockaddr_storage);
170ce0e08e2SPeter Avalos xprt_register(xprt);
171ce0e08e2SPeter Avalos return (xprt);
172ce0e08e2SPeter Avalos cleanup_svc_vc_create:
173ce0e08e2SPeter Avalos if (xprt)
174ce0e08e2SPeter Avalos mem_free(xprt, sizeof(*xprt));
175ce0e08e2SPeter Avalos if (r != NULL)
176ce0e08e2SPeter Avalos mem_free(r, sizeof(*r));
177ce0e08e2SPeter Avalos return (NULL);
178ce0e08e2SPeter Avalos }
179ce0e08e2SPeter Avalos
180ce0e08e2SPeter Avalos /*
181ce0e08e2SPeter Avalos * Like svtcp_create(), except the routine takes any *open* UNIX file
182ce0e08e2SPeter Avalos * descriptor as its first input.
183ce0e08e2SPeter Avalos */
184ce0e08e2SPeter Avalos SVCXPRT *
svc_fd_create(int fd,u_int sendsize,u_int recvsize)185ce0e08e2SPeter Avalos svc_fd_create(int fd, u_int sendsize, u_int recvsize)
186ce0e08e2SPeter Avalos {
187ce0e08e2SPeter Avalos struct sockaddr_storage ss;
188ce0e08e2SPeter Avalos socklen_t slen;
189ce0e08e2SPeter Avalos SVCXPRT *ret;
190ce0e08e2SPeter Avalos
191ce0e08e2SPeter Avalos assert(fd != -1);
192ce0e08e2SPeter Avalos
193ce0e08e2SPeter Avalos ret = makefd_xprt(fd, sendsize, recvsize);
194ce0e08e2SPeter Avalos if (ret == NULL)
195ce0e08e2SPeter Avalos return NULL;
196ce0e08e2SPeter Avalos
197ce0e08e2SPeter Avalos slen = sizeof (struct sockaddr_storage);
198ce0e08e2SPeter Avalos if (_getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) {
199ce0e08e2SPeter Avalos warnx("svc_fd_create: could not retrieve local addr");
200ce0e08e2SPeter Avalos goto freedata;
201ce0e08e2SPeter Avalos }
202ce0e08e2SPeter Avalos ret->xp_ltaddr.maxlen = ret->xp_ltaddr.len = ss.ss_len;
203ce0e08e2SPeter Avalos ret->xp_ltaddr.buf = mem_alloc((size_t)ss.ss_len);
204ce0e08e2SPeter Avalos if (ret->xp_ltaddr.buf == NULL) {
205ce0e08e2SPeter Avalos warnx("svc_fd_create: no mem for local addr");
206ce0e08e2SPeter Avalos goto freedata;
207ce0e08e2SPeter Avalos }
208ce0e08e2SPeter Avalos memcpy(ret->xp_ltaddr.buf, &ss, (size_t)ss.ss_len);
209ce0e08e2SPeter Avalos
210ce0e08e2SPeter Avalos slen = sizeof (struct sockaddr_storage);
211ce0e08e2SPeter Avalos if (_getpeername(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) {
212ce0e08e2SPeter Avalos warnx("svc_fd_create: could not retrieve remote addr");
213ce0e08e2SPeter Avalos goto freedata;
214ce0e08e2SPeter Avalos }
215ce0e08e2SPeter Avalos ret->xp_rtaddr.maxlen = ret->xp_rtaddr.len = ss.ss_len;
216ce0e08e2SPeter Avalos ret->xp_rtaddr.buf = mem_alloc((size_t)ss.ss_len);
217ce0e08e2SPeter Avalos if (ret->xp_rtaddr.buf == NULL) {
218ce0e08e2SPeter Avalos warnx("svc_fd_create: no mem for local addr");
219ce0e08e2SPeter Avalos goto freedata;
220ce0e08e2SPeter Avalos }
221ce0e08e2SPeter Avalos memcpy(ret->xp_rtaddr.buf, &ss, (size_t)ss.ss_len);
222ce0e08e2SPeter Avalos #ifdef PORTMAP
223ce0e08e2SPeter Avalos if (ss.ss_family == AF_INET || ss.ss_family == AF_LOCAL) {
224ce0e08e2SPeter Avalos ret->xp_raddr = *(struct sockaddr_in *)ret->xp_rtaddr.buf;
225ce0e08e2SPeter Avalos ret->xp_addrlen = sizeof (struct sockaddr_in);
226ce0e08e2SPeter Avalos }
227ce0e08e2SPeter Avalos #endif /* PORTMAP */
228ce0e08e2SPeter Avalos
229ce0e08e2SPeter Avalos return ret;
230ce0e08e2SPeter Avalos
231ce0e08e2SPeter Avalos freedata:
232ce0e08e2SPeter Avalos if (ret->xp_ltaddr.buf != NULL)
233ce0e08e2SPeter Avalos mem_free(ret->xp_ltaddr.buf, rep->xp_ltaddr.maxlen);
234ce0e08e2SPeter Avalos
235ce0e08e2SPeter Avalos return NULL;
236ce0e08e2SPeter Avalos }
237ce0e08e2SPeter Avalos
238ce0e08e2SPeter Avalos static SVCXPRT *
makefd_xprt(int fd,u_int sendsize,u_int recvsize)239ce0e08e2SPeter Avalos makefd_xprt(int fd, u_int sendsize, u_int recvsize)
240ce0e08e2SPeter Avalos {
241ce0e08e2SPeter Avalos SVCXPRT *xprt;
242ce0e08e2SPeter Avalos struct cf_conn *cd;
243ce0e08e2SPeter Avalos const char *netid;
244ce0e08e2SPeter Avalos struct __rpc_sockinfo si;
245ce0e08e2SPeter Avalos
246ce0e08e2SPeter Avalos assert(fd != -1);
247ce0e08e2SPeter Avalos
248ce0e08e2SPeter Avalos xprt = mem_alloc(sizeof(SVCXPRT));
249ce0e08e2SPeter Avalos if (xprt == NULL) {
250ce0e08e2SPeter Avalos warnx("svc_vc: makefd_xprt: out of memory");
251ce0e08e2SPeter Avalos goto done;
252ce0e08e2SPeter Avalos }
253ce0e08e2SPeter Avalos memset(xprt, 0, sizeof *xprt);
254ce0e08e2SPeter Avalos cd = mem_alloc(sizeof(struct cf_conn));
255ce0e08e2SPeter Avalos if (cd == NULL) {
256ce0e08e2SPeter Avalos warnx("svc_tcp: makefd_xprt: out of memory");
257ce0e08e2SPeter Avalos mem_free(xprt, sizeof(SVCXPRT));
258ce0e08e2SPeter Avalos xprt = NULL;
259ce0e08e2SPeter Avalos goto done;
260ce0e08e2SPeter Avalos }
261ce0e08e2SPeter Avalos cd->strm_stat = XPRT_IDLE;
262ce0e08e2SPeter Avalos xdrrec_create(&(cd->xdrs), sendsize, recvsize,
263ce0e08e2SPeter Avalos xprt, read_vc, write_vc);
264ce0e08e2SPeter Avalos xprt->xp_p1 = cd;
265ce0e08e2SPeter Avalos xprt->xp_verf.oa_base = cd->verf_body;
266ce0e08e2SPeter Avalos svc_vc_ops(xprt); /* truely deals with calls */
267ce0e08e2SPeter Avalos xprt->xp_port = 0; /* this is a connection, not a rendezvouser */
268ce0e08e2SPeter Avalos xprt->xp_fd = fd;
269ce0e08e2SPeter Avalos if (__rpc_fd2sockinfo(fd, &si) && __rpc_sockinfo2netid(&si, &netid))
270ce0e08e2SPeter Avalos xprt->xp_netid = strdup(netid);
271ce0e08e2SPeter Avalos
272ce0e08e2SPeter Avalos xprt_register(xprt);
273ce0e08e2SPeter Avalos done:
274ce0e08e2SPeter Avalos return (xprt);
275ce0e08e2SPeter Avalos }
276ce0e08e2SPeter Avalos
277ce0e08e2SPeter Avalos /*ARGSUSED*/
278ce0e08e2SPeter Avalos static bool_t
rendezvous_request(SVCXPRT * xprt,struct rpc_msg * msg)279ce0e08e2SPeter Avalos rendezvous_request(SVCXPRT *xprt, struct rpc_msg *msg)
280ce0e08e2SPeter Avalos {
281ce0e08e2SPeter Avalos int sock, flags;
282ce0e08e2SPeter Avalos struct cf_rendezvous *r;
283ce0e08e2SPeter Avalos struct cf_conn *cd;
284ce0e08e2SPeter Avalos struct sockaddr_storage addr;
285ce0e08e2SPeter Avalos socklen_t len;
286ce0e08e2SPeter Avalos struct __rpc_sockinfo si;
287ce0e08e2SPeter Avalos SVCXPRT *newxprt;
288ce0e08e2SPeter Avalos fd_set cleanfds;
289ce0e08e2SPeter Avalos
290ce0e08e2SPeter Avalos assert(xprt != NULL);
291ce0e08e2SPeter Avalos assert(msg != NULL);
292ce0e08e2SPeter Avalos
293ce0e08e2SPeter Avalos r = (struct cf_rendezvous *)xprt->xp_p1;
294ce0e08e2SPeter Avalos again:
295ce0e08e2SPeter Avalos len = sizeof addr;
296ce0e08e2SPeter Avalos if ((sock = _accept(xprt->xp_fd, (struct sockaddr *)(void *)&addr,
297ce0e08e2SPeter Avalos &len)) < 0) {
298ce0e08e2SPeter Avalos if (errno == EINTR)
299ce0e08e2SPeter Avalos goto again;
300ce0e08e2SPeter Avalos /*
301ce0e08e2SPeter Avalos * Clean out the most idle file descriptor when we're
302ce0e08e2SPeter Avalos * running out.
303ce0e08e2SPeter Avalos */
304ce0e08e2SPeter Avalos if (errno == EMFILE || errno == ENFILE) {
305ce0e08e2SPeter Avalos cleanfds = svc_fdset;
306ce0e08e2SPeter Avalos __svc_clean_idle(&cleanfds, 0, FALSE);
307ce0e08e2SPeter Avalos goto again;
308ce0e08e2SPeter Avalos }
309ce0e08e2SPeter Avalos return (FALSE);
310ce0e08e2SPeter Avalos }
311ce0e08e2SPeter Avalos /*
312ce0e08e2SPeter Avalos * make a new transporter (re-uses xprt)
313ce0e08e2SPeter Avalos */
314ce0e08e2SPeter Avalos newxprt = makefd_xprt(sock, r->sendsize, r->recvsize);
315ce0e08e2SPeter Avalos newxprt->xp_rtaddr.buf = mem_alloc(len);
316ce0e08e2SPeter Avalos if (newxprt->xp_rtaddr.buf == NULL)
317ce0e08e2SPeter Avalos return (FALSE);
318ce0e08e2SPeter Avalos memcpy(newxprt->xp_rtaddr.buf, &addr, len);
319ce0e08e2SPeter Avalos newxprt->xp_rtaddr.len = len;
320ce0e08e2SPeter Avalos #ifdef PORTMAP
321ce0e08e2SPeter Avalos if (addr.ss_family == AF_INET || addr.ss_family == AF_LOCAL) {
322ce0e08e2SPeter Avalos newxprt->xp_raddr = *(struct sockaddr_in *)newxprt->xp_rtaddr.buf;
323ce0e08e2SPeter Avalos newxprt->xp_addrlen = sizeof (struct sockaddr_in);
324ce0e08e2SPeter Avalos }
325ce0e08e2SPeter Avalos #endif /* PORTMAP */
326ce0e08e2SPeter Avalos if (__rpc_fd2sockinfo(sock, &si) && si.si_proto == IPPROTO_TCP) {
327ce0e08e2SPeter Avalos len = 1;
328ce0e08e2SPeter Avalos /* XXX fvdl - is this useful? */
329ce0e08e2SPeter Avalos _setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &len, sizeof (len));
330ce0e08e2SPeter Avalos }
331ce0e08e2SPeter Avalos
332ce0e08e2SPeter Avalos cd = (struct cf_conn *)newxprt->xp_p1;
333ce0e08e2SPeter Avalos
334ce0e08e2SPeter Avalos cd->recvsize = r->recvsize;
335ce0e08e2SPeter Avalos cd->sendsize = r->sendsize;
336ce0e08e2SPeter Avalos cd->maxrec = r->maxrec;
337ce0e08e2SPeter Avalos
338ce0e08e2SPeter Avalos if (cd->maxrec != 0) {
339ce0e08e2SPeter Avalos flags = _fcntl(sock, F_GETFL, 0);
340ce0e08e2SPeter Avalos if (flags == -1)
341ce0e08e2SPeter Avalos return (FALSE);
342ce0e08e2SPeter Avalos if (_fcntl(sock, F_SETFL, flags | O_NONBLOCK) == -1)
343ce0e08e2SPeter Avalos return (FALSE);
344ce0e08e2SPeter Avalos if (cd->recvsize > cd->maxrec)
345ce0e08e2SPeter Avalos cd->recvsize = cd->maxrec;
346ce0e08e2SPeter Avalos cd->nonblock = TRUE;
347ce0e08e2SPeter Avalos __xdrrec_setnonblock(&cd->xdrs, cd->maxrec);
348ce0e08e2SPeter Avalos } else
349ce0e08e2SPeter Avalos cd->nonblock = FALSE;
350ce0e08e2SPeter Avalos
351ce0e08e2SPeter Avalos gettimeofday(&cd->last_recv_time, NULL);
352ce0e08e2SPeter Avalos
353ce0e08e2SPeter Avalos return (FALSE); /* there is never an rpc msg to be processed */
354ce0e08e2SPeter Avalos }
355ce0e08e2SPeter Avalos
356ce0e08e2SPeter Avalos /*ARGSUSED*/
357ce0e08e2SPeter Avalos static enum xprt_stat
rendezvous_stat(SVCXPRT * xprt __unused)3586d7019e6SSascha Wildner rendezvous_stat(SVCXPRT *xprt __unused)
359ce0e08e2SPeter Avalos {
360ce0e08e2SPeter Avalos
361ce0e08e2SPeter Avalos return (XPRT_IDLE);
362ce0e08e2SPeter Avalos }
363ce0e08e2SPeter Avalos
364ce0e08e2SPeter Avalos static void
svc_vc_destroy(SVCXPRT * xprt)365ce0e08e2SPeter Avalos svc_vc_destroy(SVCXPRT *xprt)
366ce0e08e2SPeter Avalos {
367ce0e08e2SPeter Avalos assert(xprt != NULL);
368ce0e08e2SPeter Avalos
369ce0e08e2SPeter Avalos xprt_unregister(xprt);
370ce0e08e2SPeter Avalos __svc_vc_dodestroy(xprt);
371ce0e08e2SPeter Avalos }
372ce0e08e2SPeter Avalos
373ce0e08e2SPeter Avalos static void
__svc_vc_dodestroy(SVCXPRT * xprt)374ce0e08e2SPeter Avalos __svc_vc_dodestroy(SVCXPRT *xprt)
375ce0e08e2SPeter Avalos {
376ce0e08e2SPeter Avalos struct cf_conn *cd;
377ce0e08e2SPeter Avalos struct cf_rendezvous *r;
378ce0e08e2SPeter Avalos
379ce0e08e2SPeter Avalos cd = (struct cf_conn *)xprt->xp_p1;
380ce0e08e2SPeter Avalos
381ce0e08e2SPeter Avalos if (xprt->xp_fd != RPC_ANYFD)
382ce0e08e2SPeter Avalos _close(xprt->xp_fd);
383ce0e08e2SPeter Avalos if (xprt->xp_port != 0) {
384ce0e08e2SPeter Avalos /* a rendezvouser socket */
385ce0e08e2SPeter Avalos r = (struct cf_rendezvous *)xprt->xp_p1;
386ce0e08e2SPeter Avalos mem_free(r, sizeof (struct cf_rendezvous));
387ce0e08e2SPeter Avalos xprt->xp_port = 0;
388ce0e08e2SPeter Avalos } else {
389ce0e08e2SPeter Avalos /* an actual connection socket */
390ce0e08e2SPeter Avalos XDR_DESTROY(&(cd->xdrs));
391ce0e08e2SPeter Avalos mem_free(cd, sizeof(struct cf_conn));
392ce0e08e2SPeter Avalos }
393ce0e08e2SPeter Avalos if (xprt->xp_rtaddr.buf)
394ce0e08e2SPeter Avalos mem_free(xprt->xp_rtaddr.buf, xprt->xp_rtaddr.maxlen);
395ce0e08e2SPeter Avalos if (xprt->xp_ltaddr.buf)
396ce0e08e2SPeter Avalos mem_free(xprt->xp_ltaddr.buf, xprt->xp_ltaddr.maxlen);
397ce0e08e2SPeter Avalos if (xprt->xp_tp)
398ce0e08e2SPeter Avalos free(xprt->xp_tp);
399ce0e08e2SPeter Avalos if (xprt->xp_netid)
400ce0e08e2SPeter Avalos free(xprt->xp_netid);
401ce0e08e2SPeter Avalos mem_free(xprt, sizeof(SVCXPRT));
402ce0e08e2SPeter Avalos }
403ce0e08e2SPeter Avalos
404ce0e08e2SPeter Avalos /*ARGSUSED*/
405ce0e08e2SPeter Avalos static bool_t
svc_vc_control(SVCXPRT * xprt __unused,const u_int rq __unused,void * in __unused)4066d7019e6SSascha Wildner svc_vc_control(SVCXPRT *xprt __unused, const u_int rq __unused,
4076d7019e6SSascha Wildner void *in __unused)
408ce0e08e2SPeter Avalos {
409ce0e08e2SPeter Avalos return (FALSE);
410ce0e08e2SPeter Avalos }
411ce0e08e2SPeter Avalos
412ce0e08e2SPeter Avalos static bool_t
svc_vc_rendezvous_control(SVCXPRT * xprt,const u_int rq,void * in)413ce0e08e2SPeter Avalos svc_vc_rendezvous_control(SVCXPRT *xprt, const u_int rq, void *in)
414ce0e08e2SPeter Avalos {
415ce0e08e2SPeter Avalos struct cf_rendezvous *cfp;
416ce0e08e2SPeter Avalos
417ce0e08e2SPeter Avalos cfp = (struct cf_rendezvous *)xprt->xp_p1;
418ce0e08e2SPeter Avalos if (cfp == NULL)
419ce0e08e2SPeter Avalos return (FALSE);
420ce0e08e2SPeter Avalos switch (rq) {
421ce0e08e2SPeter Avalos case SVCGET_CONNMAXREC:
422ce0e08e2SPeter Avalos *(int *)in = cfp->maxrec;
423ce0e08e2SPeter Avalos break;
424ce0e08e2SPeter Avalos case SVCSET_CONNMAXREC:
425ce0e08e2SPeter Avalos cfp->maxrec = *(int *)in;
426ce0e08e2SPeter Avalos break;
427ce0e08e2SPeter Avalos default:
428ce0e08e2SPeter Avalos return (FALSE);
429ce0e08e2SPeter Avalos }
430ce0e08e2SPeter Avalos return (TRUE);
431ce0e08e2SPeter Avalos }
432ce0e08e2SPeter Avalos
433ce0e08e2SPeter Avalos /*
434ce0e08e2SPeter Avalos * reads data from the tcp or uip connection.
435ce0e08e2SPeter Avalos * any error is fatal and the connection is closed.
436ce0e08e2SPeter Avalos * (And a read of zero bytes is a half closed stream => error.)
437ce0e08e2SPeter Avalos * All read operations timeout after 35 seconds. A timeout is
438ce0e08e2SPeter Avalos * fatal for the connection.
439ce0e08e2SPeter Avalos */
440ce0e08e2SPeter Avalos static int
read_vc(void * xprtp,void * buf,int len)441ce0e08e2SPeter Avalos read_vc(void *xprtp, void *buf, int len)
442ce0e08e2SPeter Avalos {
443ce0e08e2SPeter Avalos SVCXPRT *xprt;
444ce0e08e2SPeter Avalos int sock;
445ce0e08e2SPeter Avalos int milliseconds = 35 * 1000;
446ce0e08e2SPeter Avalos struct pollfd pollfd;
447ce0e08e2SPeter Avalos struct cf_conn *cfp;
448ce0e08e2SPeter Avalos
449ce0e08e2SPeter Avalos xprt = (SVCXPRT *)xprtp;
450ce0e08e2SPeter Avalos assert(xprt != NULL);
451ce0e08e2SPeter Avalos
452ce0e08e2SPeter Avalos sock = xprt->xp_fd;
453ce0e08e2SPeter Avalos
454ce0e08e2SPeter Avalos cfp = (struct cf_conn *)xprt->xp_p1;
455ce0e08e2SPeter Avalos
456ce0e08e2SPeter Avalos if (cfp->nonblock) {
457ce0e08e2SPeter Avalos len = _read(sock, buf, (size_t)len);
458ce0e08e2SPeter Avalos if (len < 0) {
459ce0e08e2SPeter Avalos if (errno == EAGAIN)
460ce0e08e2SPeter Avalos len = 0;
461ce0e08e2SPeter Avalos else
462ce0e08e2SPeter Avalos goto fatal_err;
463ce0e08e2SPeter Avalos }
464ce0e08e2SPeter Avalos if (len != 0)
465ce0e08e2SPeter Avalos gettimeofday(&cfp->last_recv_time, NULL);
466ce0e08e2SPeter Avalos return len;
467ce0e08e2SPeter Avalos }
468ce0e08e2SPeter Avalos
469ce0e08e2SPeter Avalos do {
470ce0e08e2SPeter Avalos pollfd.fd = sock;
471ce0e08e2SPeter Avalos pollfd.events = POLLIN;
472ce0e08e2SPeter Avalos pollfd.revents = 0;
473ce0e08e2SPeter Avalos switch (_poll(&pollfd, 1, milliseconds)) {
474ce0e08e2SPeter Avalos case -1:
475ce0e08e2SPeter Avalos if (errno == EINTR)
476ce0e08e2SPeter Avalos continue;
477ce0e08e2SPeter Avalos /*FALLTHROUGH*/
478ce0e08e2SPeter Avalos case 0:
479ce0e08e2SPeter Avalos goto fatal_err;
480ce0e08e2SPeter Avalos
481ce0e08e2SPeter Avalos default:
482ce0e08e2SPeter Avalos break;
483ce0e08e2SPeter Avalos }
484ce0e08e2SPeter Avalos } while ((pollfd.revents & POLLIN) == 0);
485ce0e08e2SPeter Avalos
486ce0e08e2SPeter Avalos if ((len = _read(sock, buf, (size_t)len)) > 0) {
487ce0e08e2SPeter Avalos gettimeofday(&cfp->last_recv_time, NULL);
488ce0e08e2SPeter Avalos return (len);
489ce0e08e2SPeter Avalos }
490ce0e08e2SPeter Avalos
491ce0e08e2SPeter Avalos fatal_err:
492ce0e08e2SPeter Avalos ((struct cf_conn *)(xprt->xp_p1))->strm_stat = XPRT_DIED;
493ce0e08e2SPeter Avalos return (-1);
494ce0e08e2SPeter Avalos }
495ce0e08e2SPeter Avalos
496ce0e08e2SPeter Avalos /*
497ce0e08e2SPeter Avalos * writes data to the tcp connection.
498ce0e08e2SPeter Avalos * Any error is fatal and the connection is closed.
499ce0e08e2SPeter Avalos */
500ce0e08e2SPeter Avalos static int
write_vc(void * xprtp,void * buf,int len)501ce0e08e2SPeter Avalos write_vc(void *xprtp, void *buf, int len)
502ce0e08e2SPeter Avalos {
503ce0e08e2SPeter Avalos SVCXPRT *xprt;
504ce0e08e2SPeter Avalos int i, cnt;
505ce0e08e2SPeter Avalos struct cf_conn *cd;
506ce0e08e2SPeter Avalos struct timeval tv0, tv1;
507ce0e08e2SPeter Avalos
508ce0e08e2SPeter Avalos xprt = (SVCXPRT *)xprtp;
509ce0e08e2SPeter Avalos assert(xprt != NULL);
510ce0e08e2SPeter Avalos
511ce0e08e2SPeter Avalos cd = (struct cf_conn *)xprt->xp_p1;
512ce0e08e2SPeter Avalos
513ce0e08e2SPeter Avalos if (cd->nonblock)
514ce0e08e2SPeter Avalos gettimeofday(&tv0, NULL);
515ce0e08e2SPeter Avalos
516ce0e08e2SPeter Avalos for (cnt = len; cnt > 0; cnt -= i, buf = (char *)buf + i) {
517ce0e08e2SPeter Avalos i = _write(xprt->xp_fd, buf, (size_t)cnt);
518ce0e08e2SPeter Avalos if (i < 0) {
519ce0e08e2SPeter Avalos if (errno != EAGAIN || !cd->nonblock) {
520ce0e08e2SPeter Avalos cd->strm_stat = XPRT_DIED;
521ce0e08e2SPeter Avalos return (-1);
522ce0e08e2SPeter Avalos }
523ce0e08e2SPeter Avalos if (cd->nonblock && i != cnt) {
524ce0e08e2SPeter Avalos /*
525ce0e08e2SPeter Avalos * For non-blocking connections, do not
526ce0e08e2SPeter Avalos * take more than 2 seconds writing the
527ce0e08e2SPeter Avalos * data out.
528ce0e08e2SPeter Avalos *
529ce0e08e2SPeter Avalos * XXX 2 is an arbitrary amount.
530ce0e08e2SPeter Avalos */
531ce0e08e2SPeter Avalos gettimeofday(&tv1, NULL);
532ce0e08e2SPeter Avalos if (tv1.tv_sec - tv0.tv_sec >= 2) {
533ce0e08e2SPeter Avalos cd->strm_stat = XPRT_DIED;
534ce0e08e2SPeter Avalos return (-1);
535ce0e08e2SPeter Avalos }
536ce0e08e2SPeter Avalos }
537ce0e08e2SPeter Avalos }
538ce0e08e2SPeter Avalos }
539ce0e08e2SPeter Avalos
540ce0e08e2SPeter Avalos return (len);
541ce0e08e2SPeter Avalos }
542ce0e08e2SPeter Avalos
543ce0e08e2SPeter Avalos static enum xprt_stat
svc_vc_stat(SVCXPRT * xprt)544ce0e08e2SPeter Avalos svc_vc_stat(SVCXPRT *xprt)
545ce0e08e2SPeter Avalos {
546ce0e08e2SPeter Avalos struct cf_conn *cd;
547ce0e08e2SPeter Avalos
548ce0e08e2SPeter Avalos assert(xprt != NULL);
549ce0e08e2SPeter Avalos
550ce0e08e2SPeter Avalos cd = (struct cf_conn *)(xprt->xp_p1);
551ce0e08e2SPeter Avalos
552ce0e08e2SPeter Avalos if (cd->strm_stat == XPRT_DIED)
553ce0e08e2SPeter Avalos return (XPRT_DIED);
554ce0e08e2SPeter Avalos if (! xdrrec_eof(&(cd->xdrs)))
555ce0e08e2SPeter Avalos return (XPRT_MOREREQS);
556ce0e08e2SPeter Avalos return (XPRT_IDLE);
557ce0e08e2SPeter Avalos }
558ce0e08e2SPeter Avalos
559ce0e08e2SPeter Avalos static bool_t
svc_vc_recv(SVCXPRT * xprt,struct rpc_msg * msg)560ce0e08e2SPeter Avalos svc_vc_recv(SVCXPRT *xprt, struct rpc_msg *msg)
561ce0e08e2SPeter Avalos {
562ce0e08e2SPeter Avalos struct cf_conn *cd;
563ce0e08e2SPeter Avalos XDR *xdrs;
564ce0e08e2SPeter Avalos
565ce0e08e2SPeter Avalos assert(xprt != NULL);
566ce0e08e2SPeter Avalos assert(msg != NULL);
567ce0e08e2SPeter Avalos
568ce0e08e2SPeter Avalos cd = (struct cf_conn *)(xprt->xp_p1);
569ce0e08e2SPeter Avalos xdrs = &(cd->xdrs);
570ce0e08e2SPeter Avalos
571ce0e08e2SPeter Avalos if (cd->nonblock) {
572ce0e08e2SPeter Avalos if (!__xdrrec_getrec(xdrs, &cd->strm_stat, TRUE))
573ce0e08e2SPeter Avalos return FALSE;
574ce0e08e2SPeter Avalos } else {
575ce0e08e2SPeter Avalos xdrrec_skiprecord(xdrs);
576ce0e08e2SPeter Avalos }
577ce0e08e2SPeter Avalos
578ce0e08e2SPeter Avalos xdrs->x_op = XDR_DECODE;
579ce0e08e2SPeter Avalos if (xdr_callmsg(xdrs, msg)) {
580ce0e08e2SPeter Avalos cd->x_id = msg->rm_xid;
581ce0e08e2SPeter Avalos return (TRUE);
582ce0e08e2SPeter Avalos }
583ce0e08e2SPeter Avalos cd->strm_stat = XPRT_DIED;
584ce0e08e2SPeter Avalos return (FALSE);
585ce0e08e2SPeter Avalos }
586ce0e08e2SPeter Avalos
587ce0e08e2SPeter Avalos static bool_t
svc_vc_getargs(SVCXPRT * xprt,xdrproc_t xdr_args,void * args_ptr)588ce0e08e2SPeter Avalos svc_vc_getargs(SVCXPRT *xprt, xdrproc_t xdr_args, void *args_ptr)
589ce0e08e2SPeter Avalos {
590ce0e08e2SPeter Avalos
591ce0e08e2SPeter Avalos assert(xprt != NULL);
592ce0e08e2SPeter Avalos /* args_ptr may be NULL */
593ce0e08e2SPeter Avalos return ((*xdr_args)(&(((struct cf_conn *)(xprt->xp_p1))->xdrs),
594ce0e08e2SPeter Avalos args_ptr));
595ce0e08e2SPeter Avalos }
596ce0e08e2SPeter Avalos
597ce0e08e2SPeter Avalos static bool_t
svc_vc_freeargs(SVCXPRT * xprt,xdrproc_t xdr_args,void * args_ptr)598ce0e08e2SPeter Avalos svc_vc_freeargs(SVCXPRT *xprt, xdrproc_t xdr_args, void *args_ptr)
599ce0e08e2SPeter Avalos {
600ce0e08e2SPeter Avalos XDR *xdrs;
601ce0e08e2SPeter Avalos
602ce0e08e2SPeter Avalos assert(xprt != NULL);
603ce0e08e2SPeter Avalos /* args_ptr may be NULL */
604ce0e08e2SPeter Avalos
605ce0e08e2SPeter Avalos xdrs = &(((struct cf_conn *)(xprt->xp_p1))->xdrs);
606ce0e08e2SPeter Avalos
607ce0e08e2SPeter Avalos xdrs->x_op = XDR_FREE;
608ce0e08e2SPeter Avalos return ((*xdr_args)(xdrs, args_ptr));
609ce0e08e2SPeter Avalos }
610ce0e08e2SPeter Avalos
611ce0e08e2SPeter Avalos static bool_t
svc_vc_reply(SVCXPRT * xprt,struct rpc_msg * msg)612ce0e08e2SPeter Avalos svc_vc_reply(SVCXPRT *xprt, struct rpc_msg *msg)
613ce0e08e2SPeter Avalos {
614ce0e08e2SPeter Avalos struct cf_conn *cd;
615ce0e08e2SPeter Avalos XDR *xdrs;
616ce0e08e2SPeter Avalos bool_t rstat;
617ce0e08e2SPeter Avalos
618ce0e08e2SPeter Avalos assert(xprt != NULL);
619ce0e08e2SPeter Avalos assert(msg != NULL);
620ce0e08e2SPeter Avalos
621ce0e08e2SPeter Avalos cd = (struct cf_conn *)(xprt->xp_p1);
622ce0e08e2SPeter Avalos xdrs = &(cd->xdrs);
623ce0e08e2SPeter Avalos
624ce0e08e2SPeter Avalos xdrs->x_op = XDR_ENCODE;
625ce0e08e2SPeter Avalos msg->rm_xid = cd->x_id;
626ce0e08e2SPeter Avalos rstat = xdr_replymsg(xdrs, msg);
627ce0e08e2SPeter Avalos xdrrec_endofrecord(xdrs, TRUE);
628ce0e08e2SPeter Avalos return (rstat);
629ce0e08e2SPeter Avalos }
630ce0e08e2SPeter Avalos
631ce0e08e2SPeter Avalos static void
svc_vc_ops(SVCXPRT * xprt)632ce0e08e2SPeter Avalos svc_vc_ops(SVCXPRT *xprt)
633ce0e08e2SPeter Avalos {
634ce0e08e2SPeter Avalos static struct xp_ops ops;
635ce0e08e2SPeter Avalos static struct xp_ops2 ops2;
636ce0e08e2SPeter Avalos
637ce0e08e2SPeter Avalos /* VARIABLES PROTECTED BY ops_lock: ops, ops2 */
638ce0e08e2SPeter Avalos
639ce0e08e2SPeter Avalos mutex_lock(&ops_lock);
640ce0e08e2SPeter Avalos if (ops.xp_recv == NULL) {
641ce0e08e2SPeter Avalos ops.xp_recv = svc_vc_recv;
642ce0e08e2SPeter Avalos ops.xp_stat = svc_vc_stat;
643ce0e08e2SPeter Avalos ops.xp_getargs = svc_vc_getargs;
644ce0e08e2SPeter Avalos ops.xp_reply = svc_vc_reply;
645ce0e08e2SPeter Avalos ops.xp_freeargs = svc_vc_freeargs;
646ce0e08e2SPeter Avalos ops.xp_destroy = svc_vc_destroy;
647ce0e08e2SPeter Avalos ops2.xp_control = svc_vc_control;
648ce0e08e2SPeter Avalos }
649ce0e08e2SPeter Avalos xprt->xp_ops = &ops;
650ce0e08e2SPeter Avalos xprt->xp_ops2 = &ops2;
651ce0e08e2SPeter Avalos mutex_unlock(&ops_lock);
652ce0e08e2SPeter Avalos }
653ce0e08e2SPeter Avalos
654ce0e08e2SPeter Avalos static void
svc_vc_rendezvous_ops(SVCXPRT * xprt)655ce0e08e2SPeter Avalos svc_vc_rendezvous_ops(SVCXPRT *xprt)
656ce0e08e2SPeter Avalos {
657ce0e08e2SPeter Avalos static struct xp_ops ops;
658ce0e08e2SPeter Avalos static struct xp_ops2 ops2;
659ce0e08e2SPeter Avalos
660ce0e08e2SPeter Avalos mutex_lock(&ops_lock);
661ce0e08e2SPeter Avalos if (ops.xp_recv == NULL) {
662ce0e08e2SPeter Avalos ops.xp_recv = rendezvous_request;
663ce0e08e2SPeter Avalos ops.xp_stat = rendezvous_stat;
664ce0e08e2SPeter Avalos ops.xp_getargs =
665ce0e08e2SPeter Avalos (bool_t (*)(SVCXPRT *, xdrproc_t, void *))abort;
666ce0e08e2SPeter Avalos ops.xp_reply =
667ce0e08e2SPeter Avalos (bool_t (*)(SVCXPRT *, struct rpc_msg *))abort;
668ce0e08e2SPeter Avalos ops.xp_freeargs =
669*3a05fd2aSSascha Wildner (bool_t (*)(SVCXPRT *, xdrproc_t, void *))abort;
670ce0e08e2SPeter Avalos ops.xp_destroy = svc_vc_destroy;
671ce0e08e2SPeter Avalos ops2.xp_control = svc_vc_rendezvous_control;
672ce0e08e2SPeter Avalos }
673ce0e08e2SPeter Avalos xprt->xp_ops = &ops;
674ce0e08e2SPeter Avalos xprt->xp_ops2 = &ops2;
675ce0e08e2SPeter Avalos mutex_unlock(&ops_lock);
676ce0e08e2SPeter Avalos }
677ce0e08e2SPeter Avalos
678ce0e08e2SPeter Avalos /*
679ce0e08e2SPeter Avalos * Get the effective UID of the sending process. Used by rpcbind, keyserv
680ce0e08e2SPeter Avalos * and rpc.yppasswdd on AF_LOCAL.
681ce0e08e2SPeter Avalos */
682ce0e08e2SPeter Avalos int
__rpc_get_local_uid(SVCXPRT * transp,uid_t * uid)683ce0e08e2SPeter Avalos __rpc_get_local_uid(SVCXPRT *transp, uid_t *uid)
684ce0e08e2SPeter Avalos {
685ce0e08e2SPeter Avalos int sock, ret;
686ce0e08e2SPeter Avalos gid_t egid;
687ce0e08e2SPeter Avalos uid_t euid;
688ce0e08e2SPeter Avalos struct sockaddr *sa;
689ce0e08e2SPeter Avalos
690ce0e08e2SPeter Avalos sock = transp->xp_fd;
691ce0e08e2SPeter Avalos sa = (struct sockaddr *)transp->xp_rtaddr.buf;
692ce0e08e2SPeter Avalos if (sa->sa_family == AF_LOCAL) {
693ce0e08e2SPeter Avalos ret = getpeereid(sock, &euid, &egid);
694ce0e08e2SPeter Avalos if (ret == 0)
695ce0e08e2SPeter Avalos *uid = euid;
696ce0e08e2SPeter Avalos return (ret);
697ce0e08e2SPeter Avalos } else
698ce0e08e2SPeter Avalos return (-1);
699ce0e08e2SPeter Avalos }
700ce0e08e2SPeter Avalos
701ce0e08e2SPeter Avalos /*
702ce0e08e2SPeter Avalos * Destroy xprts that have not have had any activity in 'timeout' seconds.
703ce0e08e2SPeter Avalos * If 'cleanblock' is true, blocking connections (the default) are also
704ce0e08e2SPeter Avalos * cleaned. If timeout is 0, the least active connection is picked.
705ce0e08e2SPeter Avalos */
706ce0e08e2SPeter Avalos bool_t
__svc_clean_idle(fd_set * fds,int timeout,bool_t cleanblock)707ce0e08e2SPeter Avalos __svc_clean_idle(fd_set *fds, int timeout, bool_t cleanblock)
708ce0e08e2SPeter Avalos {
709ce0e08e2SPeter Avalos int i, ncleaned;
710ce0e08e2SPeter Avalos SVCXPRT *xprt, *least_active;
711ce0e08e2SPeter Avalos struct timeval tv, tdiff, tmax;
712ce0e08e2SPeter Avalos struct cf_conn *cd;
713ce0e08e2SPeter Avalos
714ce0e08e2SPeter Avalos gettimeofday(&tv, NULL);
715ce0e08e2SPeter Avalos tmax.tv_sec = tmax.tv_usec = 0;
716ce0e08e2SPeter Avalos least_active = NULL;
717ce0e08e2SPeter Avalos rwlock_wrlock(&svc_fd_lock);
718ce0e08e2SPeter Avalos for (i = ncleaned = 0; i <= svc_maxfd; i++) {
719ce0e08e2SPeter Avalos if (FD_ISSET(i, fds)) {
720ce0e08e2SPeter Avalos xprt = __svc_xports[i];
721ce0e08e2SPeter Avalos if (xprt == NULL || xprt->xp_ops == NULL ||
722ce0e08e2SPeter Avalos xprt->xp_ops->xp_recv != svc_vc_recv)
723ce0e08e2SPeter Avalos continue;
724ce0e08e2SPeter Avalos cd = (struct cf_conn *)xprt->xp_p1;
725ce0e08e2SPeter Avalos if (!cleanblock && !cd->nonblock)
726ce0e08e2SPeter Avalos continue;
727ce0e08e2SPeter Avalos if (timeout == 0) {
728ce0e08e2SPeter Avalos timersub(&tv, &cd->last_recv_time, &tdiff);
729ce0e08e2SPeter Avalos if (timercmp(&tdiff, &tmax, >)) {
730ce0e08e2SPeter Avalos tmax = tdiff;
731ce0e08e2SPeter Avalos least_active = xprt;
732ce0e08e2SPeter Avalos }
733ce0e08e2SPeter Avalos continue;
734ce0e08e2SPeter Avalos }
735ce0e08e2SPeter Avalos if (tv.tv_sec - cd->last_recv_time.tv_sec > timeout) {
736ce0e08e2SPeter Avalos __xprt_unregister_unlocked(xprt);
737ce0e08e2SPeter Avalos __svc_vc_dodestroy(xprt);
738ce0e08e2SPeter Avalos ncleaned++;
739ce0e08e2SPeter Avalos }
740ce0e08e2SPeter Avalos }
741ce0e08e2SPeter Avalos }
742ce0e08e2SPeter Avalos if (timeout == 0 && least_active != NULL) {
743ce0e08e2SPeter Avalos __xprt_unregister_unlocked(least_active);
744ce0e08e2SPeter Avalos __svc_vc_dodestroy(least_active);
745ce0e08e2SPeter Avalos ncleaned++;
746ce0e08e2SPeter Avalos }
747ce0e08e2SPeter Avalos rwlock_unlock(&svc_fd_lock);
748ce0e08e2SPeter Avalos return ncleaned > 0 ? TRUE : FALSE;
749ce0e08e2SPeter Avalos }
750