ReactOS 0.4.15-dev-7961-gdcf9eb0
svc_vc.c
Go to the documentation of this file.
1
2/*
3 * Copyright (c) 2009, Sun Microsystems, Inc.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 * - Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * - Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * - Neither the name of Sun Microsystems, Inc. nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 */
29
30//#include <sys/cdefs.h>
31
32/*
33 * svc_vc.c, Server side for Connection Oriented based RPC.
34 *
35 * Actually implements two flavors of transporter -
36 * a tcp rendezvouser (a listner and connection establisher)
37 * and a record/tcp stream.
38 */
39#include <wintirpc.h>
40//#include <pthread.h>
41#include <reentrant.h>
42//#include <sys/socket.h>
43#include <sys/types.h>
44//#include <sys/param.h>
45//#include <sys/poll.h>
46//#include <sys/un.h>
47//#include <sys/time.h>
48//#include <sys/uio.h>
49//#include <netinet/in.h>
50//#include <netinet/tcp.h>
51
52#include <assert.h>
53//#include <err.h>
54#include <errno.h>
55#include <fcntl.h>
56#include <stdio.h>
57#include <stdlib.h>
58#include <string.h>
59//#include <unistd.h>
60
61#include <rpc/rpc.h>
62
63#include "rpc_com.h"
64
65#include <getpeereid.h>
66
67
69
71static bool_t rendezvous_request(SVCXPRT *, struct rpc_msg *);
72static enum xprt_stat rendezvous_stat(SVCXPRT *);
73static void svc_vc_destroy(SVCXPRT *);
74static void __svc_vc_dodestroy (SVCXPRT *);
75static int read_vc(void *, void *, int);
76static int write_vc(void *, void *, int);
77static enum xprt_stat svc_vc_stat(SVCXPRT *);
78static bool_t svc_vc_recv(SVCXPRT *, struct rpc_msg *);
79static bool_t svc_vc_getargs(SVCXPRT *, xdrproc_t, void *);
80static bool_t svc_vc_freeargs(SVCXPRT *, xdrproc_t, void *);
81static bool_t svc_vc_reply(SVCXPRT *, struct rpc_msg *);
82static void svc_vc_rendezvous_ops(SVCXPRT *);
83static void svc_vc_ops(SVCXPRT *);
84static bool_t svc_vc_control(SVCXPRT *xprt, const u_int rq, void *in);
85static bool_t svc_vc_rendezvous_control (SVCXPRT *xprt, const u_int rq,
86 void *in);
87
88struct cf_rendezvous { /* kept in xprt->xp_p1 for rendezvouser */
91 int maxrec;
92};
93
94struct cf_conn { /* kept in xprt->xp_p1 for actual connection */
104};
105
106/*
107 * This is used to set xprt->xp_raddr in a way legacy
108 * apps can deal with
109 */
110void
112{
113 switch (ss->ss_family) {
114 case AF_INET6:
115 memcpy(&xprt->xp_raddr, ss, sizeof(struct sockaddr_in6));
116 xprt->xp_addrlen = sizeof (struct sockaddr_in6);
117 break;
118 case AF_INET:
119 memcpy(&xprt->xp_raddr, ss, sizeof(struct sockaddr_in));
120 xprt->xp_addrlen = sizeof (struct sockaddr_in);
121 break;
122 default:
123 xprt->xp_raddr.sin6_family = AF_UNSPEC;
124 xprt->xp_addrlen = sizeof (struct sockaddr);
125 break;
126 }
127}
128
129/*
130 * Usage:
131 * xprt = svc_vc_create(sock, send_buf_size, recv_buf_size);
132 *
133 * Creates, registers, and returns a (rpc) tcp based transporter.
134 * Once *xprt is initialized, it is registered as a transporter
135 * see (svc.h, xprt_register). This routine returns
136 * a NULL if a problem occurred.
137 *
138 * The filedescriptor passed in is expected to refer to a bound, but
139 * not yet connected socket.
140 *
141 * Since streams do buffered io similar to stdio, the caller can specify
142 * how big the send and receive buffers are via the second and third parms;
143 * 0 => use the system default.
144 */
145SVCXPRT *
146svc_vc_create(fd, sendsize, recvsize)
147 int fd;
148 u_int sendsize;
149 u_int recvsize;
150{
151 SVCXPRT *xprt;
152 struct cf_rendezvous *r = NULL;
153 struct __rpc_sockinfo si;
154 struct sockaddr_storage sslocal;
155 socklen_t slen;
156
157 r = mem_alloc(sizeof(*r));
158 if (r == NULL) {
159 // XXX warnx("svc_vc_create: out of memory");
160 goto cleanup_svc_vc_create;
161 }
162 if (!__rpc_fd2sockinfo(fd, &si))
163 return NULL;
164 r->sendsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsize);
165 r->recvsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsize);
166 r->maxrec = __svc_maxrec;
167 xprt = mem_alloc(sizeof(SVCXPRT));
168 if (xprt == NULL) {
169 // XXX warnx("svc_vc_create: out of memory");
170 goto cleanup_svc_vc_create;
171 }
172 xprt->xp_tp = NULL;
173 xprt->xp_p1 = r;
174 xprt->xp_p2 = NULL;
175 xprt->xp_p3 = NULL;
176 xprt->xp_verf = _null_auth;
178 xprt->xp_port = (u_short)-1; /* It is the rendezvouser */
179 xprt->xp_fd = fd;
180
181 slen = sizeof (struct sockaddr_storage);
182 if (getsockname(fd, (struct sockaddr *)(void *)&sslocal, &slen) == SOCKET_ERROR) {
183 // XXX warnx("svc_vc_create: could not retrieve local addr");
184 goto cleanup_svc_vc_create;
185 }
186
187 if (!__rpc_set_netbuf(&xprt->xp_ltaddr, &sslocal, sizeof(sslocal))) {
188 // XXX warnx("svc_vc_create: no mem for local addr");
189 goto cleanup_svc_vc_create;
190 }
191 xprt_register(xprt);
192 return (xprt);
193cleanup_svc_vc_create:
194 if (r != NULL)
195 mem_free(r, sizeof(*r));
196 return (NULL);
197}
198
199/*
200 * Like svtcp_create(), except the routine takes any *open* UNIX file
201 * descriptor as its first input.
202 */
203SVCXPRT *
204svc_fd_create(fd, sendsize, recvsize)
205 SOCKET fd;
206 u_int sendsize;
207 u_int recvsize;
208{
209 struct sockaddr_storage ss;
210 socklen_t slen;
211 SVCXPRT *ret;
212
213 assert(fd != -1);
214
215 ret = makefd_xprt(fd, sendsize, recvsize);
216 if (ret == NULL)
217 return NULL;
218
219 slen = sizeof (struct sockaddr_storage);
220 if (getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) == SOCKET_ERROR) {
221 // XXX warnx("svc_fd_create: could not retrieve local addr");
222 goto freedata;
223 }
224 if (!__rpc_set_netbuf(&ret->xp_ltaddr, &ss, sizeof(ss))) {
225 // XXX warnx("svc_fd_create: no mem for local addr");
226 goto freedata;
227 }
228
229 slen = sizeof (struct sockaddr_storage);
230 if (getpeername(fd, (struct sockaddr *)(void *)&ss, &slen) == SOCKET_ERROR) {
231 // XXX warnx("svc_fd_create: could not retrieve remote addr");
232 goto freedata;
233 }
234 if (!__rpc_set_netbuf(&ret->xp_rtaddr, &ss, sizeof(ss))) {
235 // XXX warnx("svc_fd_create: no mem for local addr");
236 goto freedata;
237 }
238
239 /* Set xp_raddr for compatibility */
241
242 return ret;
243
244freedata:
245 if (ret->xp_ltaddr.buf != NULL)
246 mem_free(ret->xp_ltaddr.buf, rep->xp_ltaddr.maxlen);
247
248 return NULL;
249}
250
251static SVCXPRT *
252makefd_xprt(fd, sendsize, recvsize)
253 SOCKET fd;
254 u_int sendsize;
255 u_int recvsize;
256{
257 SVCXPRT *xprt;
258 struct cf_conn *cd;
259 const char *netid;
260 struct __rpc_sockinfo si;
261
263
264 if (fd >= FD_SETSIZE) {
265 // XXX warnx("svc_vc: makefd_xprt: fd too high\n");
266 xprt = NULL;
267 goto done;
268 }
269
270 xprt = mem_alloc(sizeof(SVCXPRT));
271 if (xprt == NULL) {
272 // XXX warnx("svc_vc: makefd_xprt: out of memory");
273 goto done;
274 }
275 memset(xprt, 0, sizeof *xprt);
276 cd = mem_alloc(sizeof(struct cf_conn));
277 if (cd == NULL) {
278 // XXX warnx("svc_tcp: makefd_xprt: out of memory");
279 mem_free(xprt, sizeof(SVCXPRT));
280 xprt = NULL;
281 goto done;
282 }
283 cd->strm_stat = XPRT_IDLE;
284 xdrrec_create(&(cd->xdrs), sendsize, recvsize,
285 xprt, read_vc, write_vc);
286 xprt->xp_p1 = cd;
287 xprt->xp_verf.oa_base = cd->verf_body;
288 svc_vc_ops(xprt); /* truely deals with calls */
289 xprt->xp_port = 0; /* this is a connection, not a rendezvouser */
290 xprt->xp_fd = fd;
291 if (__rpc_fd2sockinfo(fd, &si) && __rpc_sockinfo2netid(&si, &netid))
292 xprt->xp_netid = strdup(netid);
293
294 xprt_register(xprt);
295done:
296 return (xprt);
297}
298
299/*ARGSUSED*/
300static bool_t
302 SVCXPRT *xprt;
303 struct rpc_msg *msg;
304{
305 SOCKET sock;
306#ifndef _WIN32
307 int flags;
308#endif
309 struct cf_rendezvous *r;
310 struct cf_conn *cd;
311 struct sockaddr_storage addr;
313 struct __rpc_sockinfo si;
314 SVCXPRT *newxprt;
315 fd_set cleanfds;
316
317 assert(xprt != NULL);
318 assert(msg != NULL);
319
320 r = (struct cf_rendezvous *)xprt->xp_p1;
321again:
322 len = sizeof addr;
323 if ((sock = accept(xprt->xp_fd, (struct sockaddr *)(void *)&addr,
324 &len)) == SOCKET_ERROR) {
325 if (errno == EINTR)
326 goto again;
327#ifndef __REACTOS__ // CVE-2018-14621
328 /*
329 * Clean out the most idle file descriptor when we're
330 * running out.
331 */
332 if (errno == EMFILE || errno == ENFILE) {
333 cleanfds = svc_fdset;
334 __svc_clean_idle(&cleanfds, 0, FALSE);
335 goto again;
336 }
337#endif
338 return (FALSE);
339 }
340 /*
341 * make a new transporter (re-uses xprt)
342 */
343
344 newxprt = makefd_xprt(sock, r->sendsize, r->recvsize);
345#ifdef __REACTOS__ // CVE-2018-14622
346 if (!newxprt)
347 return (FALSE);
348#endif
349
350 if (!__rpc_set_netbuf(&newxprt->xp_rtaddr, &addr, len))
351 return (FALSE);
352
353 __xprt_set_raddr(newxprt, &addr);
354
355 if (__rpc_fd2sockinfo(sock, &si) && si.si_proto == IPPROTO_TCP) {
356 len = 1;
357 /* XXX fvdl - is this useful? */
358 setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (const char *)&len, sizeof (len));
359 }
360
361 cd = (struct cf_conn *)newxprt->xp_p1;
362
363 cd->recvsize = r->recvsize;
364 cd->sendsize = r->sendsize;
365 cd->maxrec = r->maxrec;
366
367#ifndef _WIN32
368 if (cd->maxrec != 0) {
369 flags = fcntl(sock, F_GETFL, 0);
370 if (flags == -1)
371 return (FALSE);
372 if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) == -1)
373 return (FALSE);
374 if (cd->recvsize > cd->maxrec)
375 cd->recvsize = cd->maxrec;
376 cd->nonblock = TRUE;
377 __xdrrec_setnonblock(&cd->xdrs, cd->maxrec);
378 } else
379 cd->nonblock = FALSE;
380#endif /* _WIN32 */
381
382 gettimeofday(&cd->last_recv_time, NULL);
383
384 return (FALSE); /* there is never an rpc msg to be processed */
385}
386
387/*ARGSUSED*/
388static enum xprt_stat
390 SVCXPRT *xprt;
391{
392
393 return (XPRT_IDLE);
394}
395
396static void
398 SVCXPRT *xprt;
399{
400 assert(xprt != NULL);
401
402 xprt_unregister(xprt);
403 __svc_vc_dodestroy(xprt);
404}
405
406static void
408 SVCXPRT *xprt;
409{
410 struct cf_conn *cd;
411 struct cf_rendezvous *r;
412
413 cd = (struct cf_conn *)xprt->xp_p1;
414
415 if (xprt->xp_fd != RPC_ANYFD)
416 (void)closesocket(xprt->xp_fd);
417 if (xprt->xp_port != 0) {
418 /* a rendezvouser socket */
419 r = (struct cf_rendezvous *)xprt->xp_p1;
420 mem_free(r, sizeof (struct cf_rendezvous));
421 xprt->xp_port = 0;
422 } else {
423 /* an actual connection socket */
424 XDR_DESTROY(&(cd->xdrs));
425 mem_free(cd, sizeof(struct cf_conn));
426 }
427 if (xprt->xp_rtaddr.buf)
428 mem_free(xprt->xp_rtaddr.buf, xprt->xp_rtaddr.maxlen);
429 if (xprt->xp_ltaddr.buf)
430 mem_free(xprt->xp_ltaddr.buf, xprt->xp_ltaddr.maxlen);
431 if (xprt->xp_tp)
432 free(xprt->xp_tp);
433 if (xprt->xp_netid)
434 free(xprt->xp_netid);
435 mem_free(xprt, sizeof(SVCXPRT));
436}
437
438/*ARGSUSED*/
439static bool_t
441 SVCXPRT *xprt;
442 const u_int rq;
443 void *in;
444{
445 return (FALSE);
446}
447
448static bool_t
450 SVCXPRT *xprt;
451 const u_int rq;
452 void *in;
453{
454 struct cf_rendezvous *cfp;
455
456 cfp = (struct cf_rendezvous *)xprt->xp_p1;
457 if (cfp == NULL)
458 return (FALSE);
459 switch (rq) {
461 *(int *)in = cfp->maxrec;
462 break;
464 cfp->maxrec = *(int *)in;
465 break;
466 default:
467 return (FALSE);
468 }
469 return (TRUE);
470}
471
472/*
473 * reads data from the tcp or uip connection.
474 * any error is fatal and the connection is closed.
475 * (And a read of zero bytes is a half closed stream => error.)
476 * All read operations timeout after 35 seconds. A timeout is
477 * fatal for the connection.
478 */
479static int
481 void *xprtp;
482 void *buf;
483 int len;
484{
485 SVCXPRT *xprt;
486 SOCKET sock;
487 int milliseconds = 35 * 1000;
488 struct pollfd pollfd;
489 struct cf_conn *cfp;
490
491 xprt = (SVCXPRT *)xprtp;
492 assert(xprt != NULL);
493
494 sock = xprt->xp_fd;
495
496 cfp = (struct cf_conn *)xprt->xp_p1;
497
498 if (cfp->nonblock) {
499#ifdef _WIN32
500 len = recv(sock, buf, (size_t)len, 0);
501#else
502 len = read(sock, buf, (size_t)len);
503#endif
504 if (len == SOCKET_ERROR) {
505 if (WSAGetLastError() == EAGAIN)
506 len = 0;
507 else
508 goto fatal_err;
509 }
510 if (len != 0)
512 return len;
513 }
514
515 do {
516#ifndef __REACTOS__
517 pollfd.fd = sock;
519 pollfd.revents = 0;
520 switch (poll(&pollfd, 1, milliseconds)) {
521#else
522 /* ReactOS: use select instead of poll */
523 fd_set infd;
524 struct timeval timeout;
525
526 FD_ZERO(&infd);
527 FD_SET(sock, &infd);
528
529 timeout.tv_sec = 0;
530 timeout.tv_usec = milliseconds * 1000;
531
532 switch (select(0, &infd, NULL, NULL, &timeout)) {
533#endif
534 case -1:
535 if (errno == EINTR)
536 continue;
537 /*FALLTHROUGH*/
538 case 0:
539 goto fatal_err;
540
541 default:
542 break;
543 }
544#ifndef __REACTOS__
545 } while ((pollfd.revents & POLLIN) == 0);
546#else
547 } while (TRUE);
548#endif
549
550#ifdef _WIN32
551 if ((len = recv(sock, buf, (size_t)len, 0)) > 0) {
552#else
553 if ((len = read(sock, buf, (size_t)len)) > 0) {
554#endif
556 return (len);
557 }
558
559fatal_err:
560 ((struct cf_conn *)(xprt->xp_p1))->strm_stat = XPRT_DIED;
561 return (-1);
562}
563
564/*
565 * writes data to the tcp connection.
566 * Any error is fatal and the connection is closed.
567 */
568static int
569#ifdef __REACTOS__
570write_vc(xprtp, ptr, len)
571#else
573#endif
574 void *xprtp;
575#ifdef __REACTOS__
576 void *ptr;
577#else
578 char *buf;
579#endif
580 int len;
581{
582 SVCXPRT *xprt;
583 int i, cnt;
584 struct cf_conn *cd;
585 struct timeval tv0, tv1;
586#ifdef __REACTOS__
587 char *buf = ptr;
588#endif
589
590 xprt = (SVCXPRT *)xprtp;
591 assert(xprt != NULL);
592
593 cd = (struct cf_conn *)xprt->xp_p1;
594
595 if (cd->nonblock)
596 gettimeofday(&tv0, NULL);
597
598 for (cnt = len; cnt > 0; cnt -= i, buf += i) {
599#ifdef _WIN32
600 i = send(xprt->xp_fd, buf, (size_t)cnt, 0);
601#else
602 i = write(xprt->xp_fd, buf, (size_t)cnt);
603#endif
604 if (i == SOCKET_ERROR) {
605 if (WSAGetLastError() != EAGAIN || !cd->nonblock) {
606 cd->strm_stat = XPRT_DIED;
607 return (-1);
608 }
609 if (cd->nonblock && i != cnt) {
610 /*
611 * For non-blocking connections, do not
612 * take more than 2 seconds writing the
613 * data out.
614 *
615 * XXX 2 is an arbitrary amount.
616 */
617 gettimeofday(&tv1, NULL);
618 if (tv1.tv_sec - tv0.tv_sec >= 2) {
619 cd->strm_stat = XPRT_DIED;
620 return (-1);
621 }
622 }
623 }
624 }
625
626 return (len);
627}
628
629static enum xprt_stat
631 SVCXPRT *xprt;
632{
633 struct cf_conn *cd;
634
635 assert(xprt != NULL);
636
637 cd = (struct cf_conn *)(xprt->xp_p1);
638
639 if (cd->strm_stat == XPRT_DIED)
640 return (XPRT_DIED);
641 if (! xdrrec_eof(&(cd->xdrs)))
642 return (XPRT_MOREREQS);
643 return (XPRT_IDLE);
644}
645
646static bool_t
648 SVCXPRT *xprt;
649 struct rpc_msg *msg;
650{
651 struct cf_conn *cd;
652 XDR *xdrs;
653
654 assert(xprt != NULL);
655 assert(msg != NULL);
656
657 cd = (struct cf_conn *)(xprt->xp_p1);
658 xdrs = &(cd->xdrs);
659
660 if (cd->nonblock) {
661 if (!__xdrrec_getrec(xdrs, &cd->strm_stat, TRUE))
662 return FALSE;
663 }
664
667 if (xdr_callmsg(xdrs, msg)) {
668 cd->x_id = msg->rm_xid;
669 return (TRUE);
670 }
671 cd->strm_stat = XPRT_DIED;
672 return (FALSE);
673}
674
675static bool_t
676svc_vc_getargs(xprt, xdr_args, args_ptr)
677 SVCXPRT *xprt;
678 xdrproc_t xdr_args;
679 void *args_ptr;
680{
681
682 assert(xprt != NULL);
683 /* args_ptr may be NULL */
684 return ((*xdr_args)(&(((struct cf_conn *)(xprt->xp_p1))->xdrs),
685 args_ptr));
686}
687
688static bool_t
689svc_vc_freeargs(xprt, xdr_args, args_ptr)
690 SVCXPRT *xprt;
691 xdrproc_t xdr_args;
692 void *args_ptr;
693{
694 XDR *xdrs;
695
696 assert(xprt != NULL);
697 /* args_ptr may be NULL */
698
699 xdrs = &(((struct cf_conn *)(xprt->xp_p1))->xdrs);
700
701 xdrs->x_op = XDR_FREE;
702 return ((*xdr_args)(xdrs, args_ptr));
703}
704
705static bool_t
707 SVCXPRT *xprt;
708 struct rpc_msg *msg;
709{
710 struct cf_conn *cd;
711 XDR *xdrs;
712 bool_t rstat;
713
714 assert(xprt != NULL);
715 assert(msg != NULL);
716
717 cd = (struct cf_conn *)(xprt->xp_p1);
718 xdrs = &(cd->xdrs);
719
721 msg->rm_xid = cd->x_id;
722 rstat = xdr_replymsg(xdrs, msg);
724 return (rstat);
725}
726
727static void
729 SVCXPRT *xprt;
730{
731 static struct xp_ops ops;
732 static struct xp_ops2 ops2;
733 extern mutex_t ops_lock;
734
735/* VARIABLES PROTECTED BY ops_lock: ops, ops2 */
736
738 if (ops.xp_recv == NULL) {
739 ops.xp_recv = svc_vc_recv;
740 ops.xp_stat = svc_vc_stat;
741 ops.xp_getargs = svc_vc_getargs;
742 ops.xp_reply = svc_vc_reply;
743 ops.xp_freeargs = svc_vc_freeargs;
744 ops.xp_destroy = svc_vc_destroy;
745 ops2.xp_control = svc_vc_control;
746 }
747 xprt->xp_ops = &ops;
748 xprt->xp_ops2 = &ops2;
750}
751
752static void
754 SVCXPRT *xprt;
755{
756 static struct xp_ops ops;
757 static struct xp_ops2 ops2;
758 extern mutex_t ops_lock;
759
761 if (ops.xp_recv == NULL) {
762 ops.xp_recv = rendezvous_request;
763 ops.xp_stat = rendezvous_stat;
764 ops.xp_getargs =
765 (bool_t (*)(SVCXPRT *, xdrproc_t, void *))abort;
766 ops.xp_reply =
767 (bool_t (*)(SVCXPRT *, struct rpc_msg *))abort;
768 ops.xp_freeargs =
769 (bool_t (*)(SVCXPRT *, xdrproc_t, void *))abort,
770 ops.xp_destroy = svc_vc_destroy;
771 ops2.xp_control = svc_vc_rendezvous_control;
772 }
773 xprt->xp_ops = &ops;
774 xprt->xp_ops2 = &ops2;
776}
777
778/*
779 * Get the effective UID of the sending process. Used by rpcbind, keyserv
780 * and rpc.yppasswdd on AF_LOCAL.
781 */
782int
784 SOCKET sock;
785 int ret;
786 gid_t egid;
787 uid_t euid;
788 struct sockaddr *sa;
789
790 sock = transp->xp_fd;
791 sa = (struct sockaddr *)transp->xp_rtaddr.buf;
792 if (sa->sa_family == AF_UNIX) {
793 ret = getpeereid(sock, &euid, &egid);
794 if (ret == 0)
795 *uid = euid;
796 return (ret);
797 } else
798 return (-1);
799}
800
801#ifdef _WIN32
802void timersub( const struct timeval *tvp, const struct timeval *uvp, struct timeval *vvp )
803{
804 vvp->tv_sec = tvp->tv_sec - uvp->tv_sec;
805 vvp->tv_usec = tvp->tv_usec - uvp->tv_usec;
806 if( vvp->tv_usec < 0 )
807 {
808 --vvp->tv_sec;
809 vvp->tv_usec += 1000000;
810 }
811}
812#endif
813
814/*
815 * Destroy xprts that have not have had any activity in 'timeout' seconds.
816 * If 'cleanblock' is true, blocking connections (the default) are also
817 * cleaned. If timeout is 0, the least active connection is picked.
818 */
819bool_t
820__svc_clean_idle(fd_set *fds, int timeout, bool_t cleanblock)
821{
822 int i, ncleaned;
823 SVCXPRT *xprt, *least_active;
824 struct timeval tv, tdiff, tmax;
825 struct cf_conn *cd;
826
827 gettimeofday(&tv, NULL);
828 tmax.tv_sec = tmax.tv_usec = 0;
829 least_active = NULL;
831 for (i = ncleaned = 0; i <= svc_maxfd; i++) {
832 if (FD_ISSET(i, fds)) {
833 xprt = __svc_xports[i];
834 if (xprt == NULL || xprt->xp_ops == NULL ||
835 xprt->xp_ops->xp_recv != svc_vc_recv)
836 continue;
837 cd = (struct cf_conn *)xprt->xp_p1;
838 if (!cleanblock && !cd->nonblock)
839 continue;
840 if (timeout == 0) {
841 timersub(&tv, &cd->last_recv_time, &tdiff);
842 if (timercmp(&tdiff, &tmax, >)) {
843 tmax = tdiff;
844 least_active = xprt;
845 }
846 continue;
847 }
848 if (tv.tv_sec - cd->last_recv_time.tv_sec > timeout) {
850 __svc_vc_dodestroy(xprt);
851 ncleaned++;
852 }
853 }
854 }
855 if (timeout == 0 && least_active != NULL) {
856 __xprt_unregister_unlocked(least_active);
857 __svc_vc_dodestroy(least_active);
858 ncleaned++;
859 }
861 return ncleaned > 0 ? TRUE : FALSE;
862}
InitDirComponents & cd
#define EINTR
Definition: acclib.h:80
#define EAGAIN
Definition: acclib.h:83
#define read
Definition: acwin.h:96
#define write
Definition: acwin.h:97
#define gettimeofday(tv, tz)
Definition: adns_win32.h:159
static struct sockaddr_in sa
Definition: adnsresfilter.c:69
#define msg(x)
Definition: auth_time.c:54
#define timercmp(tvp, uvp, cmp)
Definition: rdesktop.h:184
long uid_t
Definition: various.h:8
#define free
Definition: debug_ros.c:5
#define MAX_AUTH_BYTES
Definition: auth.h:77
#define SVCGET_CONNMAXREC
Definition: svc.h:72
xprt_stat
Definition: svc.h:81
@ XPRT_IDLE
Definition: svc.h:84
@ XPRT_DIED
Definition: svc.h:82
@ XPRT_MOREREQS
Definition: svc.h:83
#define RPC_ANYFD
Definition: svc.h:328
#define SVCSET_CONNMAXREC
Definition: svc.h:73
UINT32 u_int
Definition: types.h:82
#define mem_free(ptr, bsize)
Definition: types.h:124
#define NULL
Definition: types.h:112
#define mem_alloc(bsize)
Definition: types.h:123
int32_t bool_t
Definition: types.h:101
#define TRUE
Definition: types.h:120
unsigned short u_short
Definition: types.h:81
#define FALSE
Definition: types.h:117
UINT gid_t
Definition: types.h:89
INT WSAAPI recv(IN SOCKET s, OUT CHAR FAR *buf, IN INT len, IN INT flags)
Definition: recv.c:23
INT WSAAPI select(IN INT s, IN OUT LPFD_SET readfds, IN OUT LPFD_SET writefds, IN OUT LPFD_SET exceptfds, IN CONST struct timeval *timeout)
Definition: select.c:41
INT WSAAPI send(IN SOCKET s, IN CONST CHAR FAR *buf, IN INT len, IN INT flags)
Definition: send.c:23
#define assert(x)
Definition: debug.h:53
#define ENFILE
Definition: errno.h:29
#define EMFILE
Definition: errno.h:30
#define IPPROTO_TCP
Definition: ip.h:196
#define POLLIN
Definition: linux.h:1853
#define AF_INET
Definition: tcpip.h:117
int getpeereid(int s, uid_t *euid, gid_t *egid)
Definition: getpeereid.c:46
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLuint in
Definition: glext.h:9616
GLbitfield flags
Definition: glext.h:7161
GLenum const GLvoid * addr
Definition: glext.h:9621
GLenum GLsizei len
Definition: glext.h:6722
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define ss
Definition: i386-dis.c:441
#define abort()
Definition: i386-dis.c:34
if(dx< 0)
Definition: linetemp.h:194
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
int socklen_t
Definition: tcp.c:35
static PVOID ptr
Definition: dispmode.c:27
#define O_NONBLOCK
Definition: port.h:158
mutex_t ops_lock
Definition: mt_misc.c:71
#define closesocket
Definition: ncftp.h:477
#define mutex_lock(m)
Definition: reentrant.h:128
#define rwlock_wrlock(l)
Definition: reentrant.h:140
#define mutex_unlock(m)
Definition: reentrant.h:129
#define rwlock_unlock(l)
Definition: reentrant.h:142
unsigned int u_int32_t
Definition: rosdhcp.h:35
bool_t xdr_callmsg(XDR *xdrs, struct rpc_msg *cmsg)
Definition: rpc_callmsg.c:50
struct opaque_auth _null_auth
int svc_maxfd
fd_set svc_fdset
u_int __rpc_get_t_size(int af, int proto, int size)
Definition: rpc_generic.c:139
int __rpc_fd2sockinfo(SOCKET fd, struct __rpc_sockinfo *sip)
Definition: rpc_generic.c:481
bool_t xdr_replymsg(XDR *xdrs, struct rpc_msg *rmsg)
Definition: rpc_prot.c:188
#define errno
Definition: errno.h:18
_Check_return_ _CRTIMP char *__cdecl strdup(_In_opt_z_ const char *_Src)
static int fd
Definition: io.c:51
#define memset(x, y, z)
Definition: compat.h:39
#define timersub(tvp1, tvp2)
Definition: time.h:116
INT WSAAPI getpeername(IN SOCKET s, OUT LPSOCKADDR name, IN OUT INT FAR *namelen)
Definition: sockctrl.c:167
INT WSAAPI getsockname(IN SOCKET s, OUT LPSOCKADDR name, IN OUT INT FAR *namelen)
Definition: sockctrl.c:213
INT WSAAPI setsockopt(IN SOCKET s, IN INT level, IN INT optname, IN CONST CHAR FAR *optval, IN INT optlen)
Definition: sockctrl.c:421
SOCKET WSAAPI accept(IN SOCKET s, OUT LPSOCKADDR addr, OUT INT FAR *addrlen)
Definition: socklife.c:23
SVCXPRT ** __svc_xports
int __svc_maxrec
bool_t __xdrrec_setnonblock(XDR *, int)
Definition: xdr_rec.c:663
struct netbuf * __rpc_set_netbuf(struct netbuf *, const void *, size_t)
Definition: rpc_generic.c:951
int __rpc_sockinfo2netid(struct __rpc_sockinfo *, const char **)
Definition: rpc_generic.c:580
void __xprt_unregister_unlocked(SVCXPRT *)
Definition: svc.c:134
bool_t __xdrrec_getrec(XDR *, enum xprt_stat *, bool_t)
Definition: xdr_rec.c:581
ADDRESS_FAMILY si_af
Definition: types.h:165
int si_proto
Definition: types.h:166
struct netbuf xp_rtaddr
Definition: svc.h:120
char * xp_netid
Definition: svc.h:118
void * xp_p3
Definition: svc.h:125
u_short xp_port
Definition: svc.h:92
char * xp_tp
Definition: svc.h:117
struct sockaddr_in6 xp_raddr
Definition: svc.h:110
void * xp_p2
Definition: svc.h:124
SOCKET xp_fd
Definition: svc.h:91
struct opaque_auth xp_verf
Definition: svc.h:121
const struct __rpc_svcxprt::xp_ops2 * xp_ops2
int xp_addrlen
Definition: svc.h:109
struct netbuf xp_ltaddr
Definition: svc.h:119
void * xp_p1
Definition: svc.h:123
const struct __rpc_svcxprt::xp_ops * xp_ops
Definition: xdr.h:103
enum xdr_op x_op
Definition: xdr.h:104
Definition: svc_vc.c:94
u_int recvsize
Definition: svc_vc.c:100
enum xprt_stat strm_stat
Definition: svc_vc.c:95
int maxrec
Definition: svc_vc.c:101
struct timeval last_recv_time
Definition: svc_vc.c:103
char verf_body[MAX_AUTH_BYTES]
Definition: svc_vc.c:98
u_int sendsize
Definition: svc_vc.c:99
u_int32_t x_id
Definition: svc_vc.c:96
XDR xdrs
Definition: svc_vc.c:97
bool_t nonblock
Definition: svc_vc.c:102
u_int sendsize
Definition: svc_vc.c:89
int maxrec
Definition: svc_vc.c:91
u_int recvsize
Definition: svc_vc.c:90
Definition: winsock.h:66
Definition: module.h:456
Definition: linux.h:1867
int fd
Definition: linux.h:1868
short revents
Definition: linux.h:1870
short events
Definition: linux.h:1869
Definition: tcpcore.h:1455
Definition: dhcpd.h:245
unsigned long tv_sec
Definition: linux.h:1738
unsigned long tv_usec
Definition: linux.h:1739
void xprt_register(SVCXPRT *xprt)
Definition: svc.c:97
void xprt_unregister(SVCXPRT *xprt)
Definition: svc.c:128
static SVCXPRT * makefd_xprt(SOCKET, u_int, u_int)
Definition: svc_vc.c:252
static void svc_vc_destroy(SVCXPRT *)
Definition: svc_vc.c:397
static bool_t rendezvous_request(SVCXPRT *, struct rpc_msg *)
Definition: svc_vc.c:301
static bool_t svc_vc_rendezvous_control(SVCXPRT *xprt, const u_int rq, void *in)
Definition: svc_vc.c:449
static bool_t svc_vc_freeargs(SVCXPRT *, xdrproc_t, void *)
Definition: svc_vc.c:689
void __xprt_set_raddr(SVCXPRT *xprt, const struct sockaddr_storage *ss)
Definition: svc_vc.c:111
static void svc_vc_ops(SVCXPRT *)
Definition: svc_vc.c:728
static bool_t svc_vc_reply(SVCXPRT *, struct rpc_msg *)
Definition: svc_vc.c:706
static int read_vc(void *, void *, int)
Definition: svc_vc.c:480
SVCXPRT * svc_fd_create(SOCKET fd, u_int sendsize, u_int recvsize)
Definition: svc_vc.c:204
bool_t __svc_clean_idle(fd_set *fds, int timeout, bool_t cleanblock)
Definition: svc_vc.c:820
static enum xprt_stat svc_vc_stat(SVCXPRT *)
Definition: svc_vc.c:630
static void __svc_vc_dodestroy(SVCXPRT *)
Definition: svc_vc.c:407
static bool_t svc_vc_getargs(SVCXPRT *, xdrproc_t, void *)
Definition: svc_vc.c:676
rwlock_t svc_fd_lock
Definition: mt_misc.c:22
static void svc_vc_rendezvous_ops(SVCXPRT *)
Definition: svc_vc.c:753
static bool_t svc_vc_recv(SVCXPRT *, struct rpc_msg *)
Definition: svc_vc.c:647
static int write_vc(void *, void *, int)
static bool_t svc_vc_control(SVCXPRT *xprt, const u_int rq, void *in)
Definition: svc_vc.c:440
int __rpc_get_local_uid(SVCXPRT *transp, uid_t *uid)
Definition: svc_vc.c:783
static enum xprt_stat rendezvous_stat(SVCXPRT *)
Definition: svc_vc.c:389
SVCXPRT * svc_vc_create(int fd, u_int sendsize, u_int recvsize)
Definition: svc_vc.c:146
#define TCP_NODELAY
Definition: tcpdef.h:117
int ret
#define FD_ISSET(fd, set)
Definition: winsock.h:100
#define AF_UNIX
Definition: winsock.h:345
int PASCAL FAR WSAGetLastError(void)
Definition: dllmain.c:112
#define FD_ZERO(set)
Definition: winsock.h:96
UINT_PTR SOCKET
Definition: winsock.h:47
#define SOCKET_ERROR
Definition: winsock.h:333
#define FD_SETSIZE
Definition: winsock.h:50
#define AF_INET6
Definition: winsock.h:369
#define FD_SET(fd, set)
Definition: winsock.h:89
#define AF_UNSPEC
Definition: winsock.h:344
#define poll
Definition: wintirpc.h:59
@ XDR_DECODE
Definition: xdr.h:86
@ XDR_FREE
Definition: xdr.h:87
@ XDR_ENCODE
Definition: xdr.h:85
#define XDR_DESTROY(xdrs)
Definition: xdr.h:214
bool_t(* xdrproc_t)(XDR *,...)
Definition: xdr.h:144
bool_t xdrrec_endofrecord(XDR *xdrs, bool_t sendnow)
Definition: xdr_rec.c:555
bool_t xdrrec_eof(XDR *xdrs)
Definition: xdr_rec.c:531
void xdrrec_create(XDR *xdrs, u_int sendsize, u_int recvsize, int *void *, int *readit, int *writeit)
Definition: xdr_rec.c:179
bool_t xdrrec_skiprecord(XDR *xdrs)
Definition: xdr_rec.c:496