ReactOS  0.4.14-dev-554-g2f8d847
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 
68 extern rwlock_t svc_fd_lock;
69 
71 static bool_t rendezvous_request(SVCXPRT *, struct rpc_msg *);
72 static enum xprt_stat rendezvous_stat(SVCXPRT *);
73 static void svc_vc_destroy(SVCXPRT *);
74 static void __svc_vc_dodestroy (SVCXPRT *);
75 static int read_vc(void *, void *, int);
76 static int write_vc(void *, void *, int);
77 static enum xprt_stat svc_vc_stat(SVCXPRT *);
78 static bool_t svc_vc_recv(SVCXPRT *, struct rpc_msg *);
79 static bool_t svc_vc_getargs(SVCXPRT *, xdrproc_t, void *);
80 static bool_t svc_vc_freeargs(SVCXPRT *, xdrproc_t, void *);
81 static bool_t svc_vc_reply(SVCXPRT *, struct rpc_msg *);
82 static void svc_vc_rendezvous_ops(SVCXPRT *);
83 static void svc_vc_ops(SVCXPRT *);
84 static bool_t svc_vc_control(SVCXPRT *xprt, const u_int rq, void *in);
85 static bool_t svc_vc_rendezvous_control (SVCXPRT *xprt, const u_int rq,
86  void *in);
87 
88 struct cf_rendezvous { /* kept in xprt->xp_p1 for rendezvouser */
91  int maxrec;
92 };
93 
94 struct cf_conn { /* kept in xprt->xp_p1 for actual connection */
101  int maxrec;
104 };
105 
106 /*
107  * This is used to set xprt->xp_raddr in a way legacy
108  * apps can deal with
109  */
110 void
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  */
145 SVCXPRT *
146 svc_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;
177  svc_vc_rendezvous_ops(xprt);
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);
193 cleanup_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  */
203 SVCXPRT *
204 svc_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 
244 freedata:
245  if (ret->xp_ltaddr.buf != NULL)
246  mem_free(ret->xp_ltaddr.buf, rep->xp_ltaddr.maxlen);
247 
248  return NULL;
249 }
250 
251 static SVCXPRT *
252 makefd_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 
262  assert(fd != SOCKET_ERROR);
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);
295 done:
296  return (xprt);
297 }
298 
299 /*ARGSUSED*/
300 static 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;
312  socklen_t len;
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;
321 again:
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*/
388 static enum xprt_stat
390  SVCXPRT *xprt;
391 {
392 
393  return (XPRT_IDLE);
394 }
395 
396 static void
398  SVCXPRT *xprt;
399 {
400  assert(xprt != NULL);
401 
402  xprt_unregister(xprt);
403  __svc_vc_dodestroy(xprt);
404 }
405 
406 static 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*/
439 static bool_t
440 svc_vc_control(xprt, rq, in)
441  SVCXPRT *xprt;
442  const u_int rq;
443  void *in;
444 {
445  return (FALSE);
446 }
447 
448 static 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) {
460  case SVCGET_CONNMAXREC:
461  *(int *)in = cfp->maxrec;
462  break;
463  case SVCSET_CONNMAXREC:
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  */
479 static int
480 read_vc(xprtp, buf, len)
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;
518  pollfd.events = POLLIN;
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 
559 fatal_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  */
568 static int
569 #ifdef __REACTOS__
570 write_vc(xprtp, ptr, len)
571 #else
572 write_vc(xprtp, buf, len)
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 
629 static 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 
646 static 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 
665  xdrs->x_op = XDR_DECODE;
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 
675 static bool_t
676 svc_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 
688 static bool_t
689 svc_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 
705 static 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 
720  xdrs->x_op = XDR_ENCODE;
721  msg->rm_xid = cd->x_id;
722  rstat = xdr_replymsg(xdrs, msg);
724  return (rstat);
725 }
726 
727 static 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 
752 static 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  */
782 int
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
802 void 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  */
819 bool_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 }
Definition: winsock.h:66
u_int __rpc_get_t_size(int af, int proto, int size)
Definition: rpc_generic.c:139
#define SOCKET_ERROR
Definition: winsock.h:333
int maxrec
Definition: svc_vc.c:91
bool_t xdrrec_eof(XDR *xdrs)
Definition: xdr_rec.c:531
#define MAX_AUTH_BYTES
Definition: auth.h:77
#define TRUE
Definition: types.h:120
xprt_stat
Definition: svc.h:81
bool_t __xdrrec_setnonblock(XDR *, int)
Definition: xdr_rec.c:663
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
static SOCKET sock
Definition: syslog.c:45
#define rwlock_wrlock(l)
Definition: reentrant.h:140
mutex_t ops_lock
Definition: mt_misc.c:71
ADDRESS_FAMILY si_af
Definition: types.h:165
static bool_t rendezvous_request(SVCXPRT *, struct rpc_msg *)
Definition: svc_vc.c:301
int si_proto
Definition: types.h:166
SVCXPRT ** __svc_xports
Definition: rpc_com.h:96
#define closesocket
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
int32_t bool_t
Definition: types.h:101
static bool_t svc_vc_getargs(SVCXPRT *, xdrproc_t, void *)
Definition: svc_vc.c:676
XDR xdrs
Definition: svc_vc.c:97
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
static struct cd_image cd
Definition: cdmake.c:182
#define RPC_ANYFD
Definition: svc.h:328
#define O_NONBLOCK
Definition: port.h:158
Definition: svc.h:82
#define free
Definition: debug_ros.c:5
fd_set svc_fdset
#define EINTR
Definition: acclib.h:80
unsigned long tv_sec
Definition: linux.h:1738
static bool_t svc_vc_recv(SVCXPRT *, struct rpc_msg *)
Definition: svc_vc.c:647
static enum xprt_stat rendezvous_stat(SVCXPRT *)
Definition: svc_vc.c:389
bool_t xdrrec_endofrecord(XDR *xdrs, bool_t sendnow)
Definition: xdr_rec.c:555
#define assert(x)
Definition: debug.h:53
u_int32_t x_id
Definition: svc_vc.c:96
static int fd
Definition: io.c:51
u_short xp_port
Definition: svc.h:92
Definition: dhcpd.h:245
Definition: svc.h:84
void __xprt_unregister_unlocked(SVCXPRT *)
Definition: svc.c:134
int errno
void xprt_unregister(SVCXPRT *xprt)
Definition: svc.c:128
#define FD_ZERO(set)
Definition: winsock.h:96
#define FD_SET(fd, set)
Definition: winsock.h:89
long uid_t
Definition: various.h:8
Definition: xdr.h:103
void __xprt_set_raddr(SVCXPRT *xprt, const struct sockaddr_storage *ss)
Definition: svc_vc.c:111
#define mutex_lock(m)
Definition: reentrant.h:128
bool_t nonblock
Definition: svc_vc.c:102
#define TCP_NODELAY
Definition: tcpdef.h:117
static SVCXPRT * makefd_xprt(SOCKET, u_int, u_int)
Definition: svc_vc.c:252
#define timersub(tvp1, tvp2)
Definition: time.h:116
#define write
Definition: acwin.h:97
#define mutex_unlock(m)
Definition: reentrant.h:129
#define gettimeofday(tv, tz)
Definition: adns_win32.h:159
bool_t(* xdrproc_t)(XDR *,...)
Definition: xdr.h:144
short events
Definition: linux.h:1869
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 mem_alloc(bsize)
Definition: types.h:123
struct opaque_auth _null_auth
int __rpc_fd2sockinfo(SOCKET fd, struct __rpc_sockinfo *sip)
Definition: rpc_generic.c:481
static bool_t svc_vc_control(SVCXPRT *xprt, const u_int rq, void *in)
Definition: svc_vc.c:440
UINT gid_t
Definition: types.h:89
#define FD_ISSET(fd, set)
Definition: winsock.h:100
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 getpeereid(int s, uid_t *euid, gid_t *egid)
Definition: getpeereid.c:46
#define rwlock_unlock(l)
Definition: reentrant.h:142
_Check_return_ _CRTIMP char *__cdecl strdup(_In_opt_z_ const char *_Src)
char verf_body[MAX_AUTH_BYTES]
Definition: svc_vc.c:98
INT WSAAPI setsockopt(IN SOCKET s, IN INT level, IN INT optname, IN CONST CHAR FAR *optval, IN INT optlen)
Definition: sockctrl.c:421
static PVOID ptr
Definition: dispmode.c:27
char * xp_tp
Definition: svc.h:117
smooth NULL
Definition: ftsmooth.c:416
unsigned long tv_usec
Definition: linux.h:1739
#define AF_INET6
Definition: winsock.h:369
Definition: arc.h:35
struct netbuf xp_ltaddr
Definition: svc.h:119
enum xprt_stat strm_stat
Definition: svc_vc.c:95
const struct __rpc_svcxprt::xp_ops * xp_ops
#define AF_UNSPEC
Definition: winsock.h:344
bool_t xdr_callmsg(XDR *xdrs, struct rpc_msg *cmsg)
Definition: rpc_callmsg.c:50
INT WSAAPI getpeername(IN SOCKET s, OUT LPSOCKADDR name, IN OUT INT FAR *namelen)
Definition: sockctrl.c:167
rwlock_t svc_fd_lock
Definition: mt_misc.c:22
#define FD_SETSIZE
Definition: winsock.h:50
#define SVCGET_CONNMAXREC
Definition: svc.h:72
INT WSAAPI WSAGetLastError(VOID)
Definition: dllmain.c:112
static bool_t svc_vc_freeargs(SVCXPRT *, xdrproc_t, void *)
Definition: svc_vc.c:689
SOCKET xp_fd
Definition: svc.h:91
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define SVCSET_CONNMAXREC
Definition: svc.h:73
INT WSAAPI send(IN SOCKET s, IN CONST CHAR FAR *buf, IN INT len, IN INT flags)
Definition: send.c:23
int poll(struct pollfd *ufds, int nfds, int timeout)
Definition: adnstest.c:68
void xprt_register(SVCXPRT *xprt)
Definition: svc.c:97
enum xdr_op x_op
Definition: xdr.h:104
static bool_t svc_vc_reply(SVCXPRT *, struct rpc_msg *)
Definition: svc_vc.c:706
int socklen_t
Definition: tcp.c:35
#define POLLIN
Definition: linux.h:1853
Definition: linux.h:1867
Definition: svc_vc.c:94
struct netbuf * __rpc_set_netbuf(struct netbuf *, const void *, size_t)
Definition: rpc_generic.c:951
static enum xprt_stat svc_vc_stat(SVCXPRT *)
Definition: svc_vc.c:630
unsigned short u_short
Definition: types.h:81
GLbitfield flags
Definition: glext.h:7161
struct sockaddr_in6 xp_raddr
Definition: svc.h:110
int ret
GLenum const GLvoid * addr
Definition: glext.h:9621
void * xp_p2
Definition: svc.h:124
Definition: xdr.h:85
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
unsigned int u_int32_t
Definition: rosdhcp.h:35
u_int sendsize
Definition: svc_vc.c:99
void * xp_p1
Definition: svc.h:123
static void svc_vc_rendezvous_ops(SVCXPRT *)
Definition: svc_vc.c:753
#define ENFILE
Definition: errno.h:29
SOCKET WSAAPI accept(IN SOCKET s, OUT LPSOCKADDR addr, OUT INT FAR *addrlen)
Definition: socklife.c:23
u_int recvsize
Definition: svc_vc.c:90
int svc_maxfd
int fd
Definition: linux.h:1868
static int read_vc(void *, void *, int)
Definition: svc_vc.c:480
u_int recvsize
Definition: svc_vc.c:100
GLuint in
Definition: glext.h:9616
u_int sendsize
Definition: svc_vc.c:89
static void __svc_vc_dodestroy(SVCXPRT *)
Definition: svc_vc.c:407
struct netbuf xp_rtaddr
Definition: svc.h:120
struct timeval last_recv_time
Definition: svc_vc.c:103
UINT32 u_int
Definition: types.h:82
int __rpc_sockinfo2netid(struct __rpc_sockinfo *, const char **)
Definition: rpc_generic.c:580
#define abort()
Definition: i386-dis.c:35
int maxrec
Definition: svc_vc.c:101
Definition: arc.h:42
int xp_addrlen
Definition: svc.h:109
static void svc_vc_destroy(SVCXPRT *)
Definition: svc_vc.c:397
short revents
Definition: linux.h:1870
Definition: tcpcore.h:1455
#define AF_UNIX
Definition: winsock.h:345
#define msg(x)
Definition: auth_time.c:54
#define timercmp(tvp, uvp, cmp)
Definition: rdesktop.h:184
Definition: xdr.h:87
struct opaque_auth xp_verf
Definition: svc.h:121
static void svc_vc_ops(SVCXPRT *)
Definition: svc_vc.c:728
Definition: xdr.h:86
void * xp_p3
Definition: svc.h:125
#define AF_INET
Definition: tcpip.h:117
#define mem_free(ptr, bsize)
Definition: types.h:124
bool_t xdrrec_skiprecord(XDR *xdrs)
Definition: xdr_rec.c:496
UINT_PTR SOCKET
Definition: winsock.h:47
int __svc_maxrec
Definition: rpc_com.h:97
int __rpc_get_local_uid(SVCXPRT *transp, uid_t *uid)
Definition: svc_vc.c:783
bool_t __xdrrec_getrec(XDR *, enum xprt_stat *, bool_t)
Definition: xdr_rec.c:581
#define ss
Definition: i386-dis.c:432
Definition: module.h:446
static int write_vc(void *, void *, int)
SVCXPRT * svc_fd_create(SOCKET fd, u_int sendsize, u_int recvsize)
Definition: svc_vc.c:204
#define memset(x, y, z)
Definition: compat.h:39
char * xp_netid
Definition: svc.h:118
bool_t xdr_replymsg(XDR *xdrs, struct rpc_msg *rmsg)
Definition: rpc_prot.c:188
INT WSAAPI recv(IN SOCKET s, OUT CHAR FAR *buf, IN INT len, IN INT flags)
Definition: recv.c:23
SVCXPRT * svc_vc_create(int fd, u_int sendsize, u_int recvsize)
Definition: svc_vc.c:146
INT WSAAPI getsockname(IN SOCKET s, OUT LPSOCKADDR name, IN OUT INT FAR *namelen)
Definition: sockctrl.c:213
static bool_t svc_vc_rendezvous_control(SVCXPRT *xprt, const u_int rq, void *in)
Definition: svc_vc.c:449
bool_t __svc_clean_idle(fd_set *fds, int timeout, bool_t cleanblock)
Definition: svc_vc.c:820
static struct sockaddr_in sa
Definition: adnsresfilter.c:69
#define XDR_DESTROY(xdrs)
Definition: xdr.h:214
void xdrrec_create(XDR *xdrs, u_int sendsize, u_int recvsize, int *void *, int *readit, int *writeit)
Definition: xdr_rec.c:179
_CRTIMP int __cdecl read(_In_ int _FileHandle, _Out_writes_bytes_(_MaxCharCount) void *_DstBuf, _In_ unsigned int _MaxCharCount)
const struct __rpc_svcxprt::xp_ops2 * xp_ops2