/*
- * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
- * unrestricted use provided that this legend is included on all tape
- * media and as a part of the software program in whole or part. Users
- * may copy or modify Sun RPC without charge, but are not authorized
- * to license or distribute it to anyone else except as part of a product or
- * program developed by the user.
+ * svc.c, Server-side remote procedure call interface.
*
- * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
- * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * There are two sets of procedures here. The xprt routines are
+ * for handling transport handles. The svc routines handle the
+ * list of service routines.
+ * Copyright (C) 2002-2019 Free Software Foundation, Inc.
+ * This file is part of the GNU C Library.
+ * Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
*
- * Sun RPC is provided with no support and without any obligation on the
- * part of Sun Microsystems, Inc. to assist in its use, correction,
- * modification or enhancement.
+ * The GNU C Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
*
- * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
- * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
- * OR ANY PART THEREOF.
+ * The GNU C Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * In no event will Sun Microsystems, Inc. be liable for any lost revenue
- * or profits or other special, indirect and consequential damages, even if
- * Sun has been advised of the possibility of such damages.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the GNU C Library; if not, see
+ * <https://www.gnu.org/licenses/>.
*
- * Sun Microsystems, Inc.
- * 2550 Garcia Avenue
- * Mountain View, California 94043
- */
-/*
- * svc.c, Server-side remote procedure call interface.
+ * Copyright (c) 2010, Oracle America, Inc.
*
- * There are two sets of procedures here. The xprt routines are
- * for handling transport handles. The svc routines handle the
- * list of service routines.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ * * Neither the name of the "Oracle America, Inc." nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
*
- * Copyright (C) 1984, Sun Microsystems, Inc.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <errno.h>
#include <rpc/svc.h>
#include <rpc/pmap_clnt.h>
#include <sys/poll.h>
+#include <time.h>
+#include <shlib-compat.h>
-static SVCXPRT **xports;
+#define xports RPC_THREAD_VARIABLE(svc_xports_s)
#define NULL_SVC ((struct svc_callout *)0)
#define RQCRED_SIZE 400 /* this size is excessive */
Each entry represents a set of procedures (an rpc program).
The dispatch routine takes request structs and runs the
appropriate procedure. */
-static struct svc_callout {
+struct svc_callout {
struct svc_callout *sc_next;
rpcprog_t sc_prog;
rpcvers_t sc_vers;
void (*sc_dispatch) (struct svc_req *, SVCXPRT *);
-} *svc_head;
+ bool_t sc_mapped;
+};
+#define svc_head RPC_THREAD_VARIABLE(svc_head_s)
/* *************** SVCXPRT related stuff **************** */
if (xports == NULL)
{
- xports = (SVCXPRT **) malloc (_rpc_dtablesize () * sizeof (SVCXPRT *));
- if (xports == NULL) /* Donยดt add handle */
+ xports = (SVCXPRT **) calloc (_rpc_dtablesize (), sizeof (SVCXPRT *));
+ if (xports == NULL) /* Don't add handle */
return;
}
if (sock < _rpc_dtablesize ())
{
+ struct pollfd *new_svc_pollfd;
+
xports[sock] = xprt;
if (sock < FD_SETSIZE)
FD_SET (sock, &svc_fdset);
return;
}
- ++svc_max_pollfd;
- svc_pollfd = realloc (svc_pollfd,
- sizeof (struct pollfd) * svc_max_pollfd);
- if (svc_pollfd == NULL) /* Out of memory */
+ new_svc_pollfd = (struct pollfd *) realloc (svc_pollfd,
+ sizeof (struct pollfd)
+ * (svc_max_pollfd + 1));
+ if (new_svc_pollfd == NULL) /* Out of memory */
return;
+ svc_pollfd = new_svc_pollfd;
+ ++svc_max_pollfd;
svc_pollfd[svc_max_pollfd - 1].fd = sock;
svc_pollfd[svc_max_pollfd - 1].events = (POLLIN | POLLPRI |
POLLRDNORM | POLLRDBAND);
}
}
+libc_hidden_nolink_sunrpc (xprt_register, GLIBC_2_0)
/* De-activate a transport handle. */
void
svc_pollfd[i].fd = -1;
}
}
+#ifdef EXPORT_RPC_SYMBOLS
+libc_hidden_def (xprt_unregister)
+#else
+libc_hidden_nolink_sunrpc (xprt_unregister, GLIBC_2_0)
+#endif
/* ********************** CALLOUT list related stuff ************* */
s->sc_vers = vers;
s->sc_dispatch = dispatch;
s->sc_next = svc_head;
+ s->sc_mapped = FALSE;
svc_head = s;
pmap_it:
/* now register the information with the local binder service */
if (protocol)
- return pmap_set (prog, vers, protocol, xprt->xp_port);
+ {
+ if (! pmap_set (prog, vers, protocol, xprt->xp_port))
+ return FALSE;
+
+ s->sc_mapped = TRUE;
+ }
return TRUE;
}
+#ifdef EXPORT_RPC_SYMBOLS
+libc_hidden_def (svc_register)
+#else
+libc_hidden_nolink_sunrpc (svc_register, GLIBC_2_0)
+#endif
/* Remove a service program from the callout list. */
void
if ((s = svc_find (prog, vers, &prev)) == NULL_SVC)
return;
+ bool is_mapped = s->sc_mapped;
if (prev == NULL_SVC)
svc_head = s->sc_next;
s->sc_next = NULL_SVC;
mem_free ((char *) s, (u_int) sizeof (struct svc_callout));
/* now unregister the information with the local binder service */
- pmap_unset (prog, vers);
+ if (is_mapped)
+ pmap_unset (prog, vers);
}
+libc_hidden_nolink_sunrpc (svc_unregister, GLIBC_2_0)
/* ******************* REPLY GENERATION ROUTINES ************ */
rply.acpted_rply.ar_results.proc = xdr_results;
return SVC_REPLY (xprt, &rply);
}
+#ifdef EXPORT_RPC_SYMBOLS
+libc_hidden_def (svc_sendreply)
+#else
+libc_hidden_nolink_sunrpc (svc_sendreply, GLIBC_2_0)
+#endif
/* No procedure error reply */
void
rply.acpted_rply.ar_stat = PROC_UNAVAIL;
SVC_REPLY (xprt, &rply);
}
+#ifdef EXPORT_RPC_SYMBOLS
+libc_hidden_def (svcerr_noproc)
+#else
+libc_hidden_nolink_sunrpc (svcerr_noproc, GLIBC_2_0)
+#endif
/* Can't decode args error reply */
void
rply.acpted_rply.ar_stat = GARBAGE_ARGS;
SVC_REPLY (xprt, &rply);
}
+#ifdef EXPORT_RPC_SYMBOLS
+libc_hidden_def (svcerr_decode)
+#else
+libc_hidden_nolink_sunrpc (svcerr_decode, GLIBC_2_0)
+#endif
/* Some system error */
void
rply.acpted_rply.ar_stat = SYSTEM_ERR;
SVC_REPLY (xprt, &rply);
}
+#ifdef EXPORT_RPC_SYMBOLS
+libc_hidden_def (svcerr_systemerr)
+#else
+libc_hidden_nolink_sunrpc (svcerr_systemerr, GLIBC_2_0)
+#endif
/* Authentication error reply */
void
rply.rjcted_rply.rj_why = why;
SVC_REPLY (xprt, &rply);
}
+libc_hidden_nolink_sunrpc (svcerr_auth, GLIBC_2_0)
/* Auth too weak error reply */
void
{
svcerr_auth (xprt, AUTH_TOOWEAK);
}
+libc_hidden_nolink_sunrpc (svcerr_weakauth, GLIBC_2_0)
/* Program unavailable error reply */
void
rply.acpted_rply.ar_stat = PROG_UNAVAIL;
SVC_REPLY (xprt, &rply);
}
+libc_hidden_nolink_sunrpc (svcerr_noprog, GLIBC_2_0)
/* Program version mismatch error reply */
void
rply.acpted_rply.ar_vers.high = high_vers;
SVC_REPLY (xprt, &rply);
}
+libc_hidden_nolink_sunrpc (svcerr_progvers, GLIBC_2_0)
/* ******************* SERVER INPUT STUFF ******************* */
readfds.fds_bits[0] = rdfds;
svc_getreqset (&readfds);
}
+libc_hidden_nolink_sunrpc (svc_getreq, GLIBC_2_0)
void
svc_getreqset (fd_set *readfds)
{
- register u_int32_t mask;
- register u_int32_t *maskp;
+ register fd_mask mask;
+ register fd_mask *maskp;
register int setsize;
register int sock;
register int bit;
setsize = _rpc_dtablesize ();
- maskp = (u_int32_t *) readfds->fds_bits;
- for (sock = 0; sock < setsize; sock += 32)
- for (mask = *maskp++; (bit = ffs (mask)); mask ^= (1 << (bit - 1)))
+ if (setsize > FD_SETSIZE)
+ setsize = FD_SETSIZE;
+ maskp = readfds->fds_bits;
+ for (sock = 0; sock < setsize; sock += NFDBITS)
+ for (mask = *maskp++; (bit = ffsl (mask)); mask ^= (1L << (bit - 1)))
svc_getreq_common (sock + bit - 1);
}
+libc_hidden_nolink_sunrpc (svc_getreqset, GLIBC_2_0)
void
svc_getreq_poll (struct pollfd *pfdp, int pollretval)
{
- register int i;
- register int fds_found;
+ if (pollretval == 0)
+ return;
- for (i = fds_found = 0; i < svc_max_pollfd && fds_found < pollretval; ++i)
+ register int fds_found;
+ for (int i = fds_found = 0; i < svc_max_pollfd; ++i)
{
register struct pollfd *p = &pfdp[i];
if (p->fd != -1 && p->revents)
{
/* fd has input waiting */
- ++fds_found;
-
if (p->revents & POLLNVAL)
- xprt_unregister (p->fd);
+ xprt_unregister (xports[p->fd]);
else
svc_getreq_common (p->fd);
+
+ if (++fds_found >= pollretval)
+ break;
}
}
}
+#ifdef EXPORT_RPC_SYMBOLS
+libc_hidden_def (svc_getreq_poll)
+#else
+libc_hidden_nolink_sunrpc (svc_getreq_poll, GLIBC_2_2)
+#endif
void
}
while (stat == XPRT_MOREREQS);
}
+libc_hidden_nolink_sunrpc (svc_getreq_common, GLIBC_2_2)
+
+/* If there are no file descriptors available, then accept will fail.
+ We want to delay here so the connection request can be dequeued;
+ otherwise we can bounce between polling and accepting, never giving the
+ request a chance to dequeue and eating an enormous amount of cpu time
+ in svc_run if we're polling on many file descriptors. */
+void
+__svc_accept_failed (void)
+{
+ if (errno == EMFILE)
+ {
+ struct timespec ts = { .tv_sec = 0, .tv_nsec = 50000000 };
+ __nanosleep (&ts, NULL);
+ }
+}
+
+
+void
+__rpc_thread_svc_cleanup (void)
+{
+ struct svc_callout *svcp;
+
+ while ((svcp = svc_head) != NULL)
+ svc_unregister (svcp->sc_prog, svcp->sc_vers);
+}