svc.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571
  1. /*
  2. * svc.c, Server-side remote procedure call interface.
  3. *
  4. * There are two sets of procedures here. The xprt routines are
  5. * for handling transport handles. The svc routines handle the
  6. * list of service routines.
  7. * Copyright (C) 2002-2019 Free Software Foundation, Inc.
  8. * This file is part of the GNU C Library.
  9. * Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
  10. *
  11. * The GNU C Library is free software; you can redistribute it and/or
  12. * modify it under the terms of the GNU Lesser General Public
  13. * License as published by the Free Software Foundation; either
  14. * version 2.1 of the License, or (at your option) any later version.
  15. *
  16. * The GNU C Library is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  19. * Lesser General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU Lesser General Public
  22. * License along with the GNU C Library; if not, see
  23. * <http://www.gnu.org/licenses/>.
  24. *
  25. * Copyright (c) 2010, Oracle America, Inc.
  26. *
  27. * Redistribution and use in source and binary forms, with or without
  28. * modification, are permitted provided that the following conditions are
  29. * met:
  30. *
  31. * * Redistributions of source code must retain the above copyright
  32. * notice, this list of conditions and the following disclaimer.
  33. * * Redistributions in binary form must reproduce the above
  34. * copyright notice, this list of conditions and the following
  35. * disclaimer in the documentation and/or other materials
  36. * provided with the distribution.
  37. * * Neither the name of the "Oracle America, Inc." nor the names of its
  38. * contributors may be used to endorse or promote products derived
  39. * from this software without specific prior written permission.
  40. *
  41. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  42. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  43. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  44. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  45. * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  46. * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  47. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  48. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  49. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  50. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  51. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  52. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  53. */
  54. #include <errno.h>
  55. #include <unistd.h>
  56. #include <rpc/rpc.h>
  57. #include <rpc/svc.h>
  58. #include <rpc/pmap_clnt.h>
  59. #include <sys/poll.h>
  60. #include <time.h>
  61. #include <shlib-compat.h>
  62. #define xports RPC_THREAD_VARIABLE(svc_xports_s)
  63. #define NULL_SVC ((struct svc_callout *)0)
  64. #define RQCRED_SIZE 400 /* this size is excessive */
  65. /* The services list
  66. Each entry represents a set of procedures (an rpc program).
  67. The dispatch routine takes request structs and runs the
  68. appropriate procedure. */
  69. struct svc_callout {
  70. struct svc_callout *sc_next;
  71. rpcprog_t sc_prog;
  72. rpcvers_t sc_vers;
  73. void (*sc_dispatch) (struct svc_req *, SVCXPRT *);
  74. bool_t sc_mapped;
  75. };
  76. #define svc_head RPC_THREAD_VARIABLE(svc_head_s)
  77. /* *************** SVCXPRT related stuff **************** */
  78. /* Activate a transport handle. */
  79. void
  80. xprt_register (SVCXPRT *xprt)
  81. {
  82. register int sock = xprt->xp_sock;
  83. register int i;
  84. if (xports == NULL)
  85. {
  86. xports = (SVCXPRT **) calloc (_rpc_dtablesize (), sizeof (SVCXPRT *));
  87. if (xports == NULL) /* Don't add handle */
  88. return;
  89. }
  90. if (sock < _rpc_dtablesize ())
  91. {
  92. struct pollfd *new_svc_pollfd;
  93. xports[sock] = xprt;
  94. if (sock < FD_SETSIZE)
  95. FD_SET (sock, &svc_fdset);
  96. /* Check if we have an empty slot */
  97. for (i = 0; i < svc_max_pollfd; ++i)
  98. if (svc_pollfd[i].fd == -1)
  99. {
  100. svc_pollfd[i].fd = sock;
  101. svc_pollfd[i].events = (POLLIN | POLLPRI |
  102. POLLRDNORM | POLLRDBAND);
  103. return;
  104. }
  105. new_svc_pollfd = (struct pollfd *) realloc (svc_pollfd,
  106. sizeof (struct pollfd)
  107. * (svc_max_pollfd + 1));
  108. if (new_svc_pollfd == NULL) /* Out of memory */
  109. return;
  110. svc_pollfd = new_svc_pollfd;
  111. ++svc_max_pollfd;
  112. svc_pollfd[svc_max_pollfd - 1].fd = sock;
  113. svc_pollfd[svc_max_pollfd - 1].events = (POLLIN | POLLPRI |
  114. POLLRDNORM | POLLRDBAND);
  115. }
  116. }
  117. libc_hidden_nolink_sunrpc (xprt_register, GLIBC_2_0)
  118. /* De-activate a transport handle. */
  119. void
  120. xprt_unregister (SVCXPRT *xprt)
  121. {
  122. register int sock = xprt->xp_sock;
  123. register int i;
  124. if ((sock < _rpc_dtablesize ()) && (xports[sock] == xprt))
  125. {
  126. xports[sock] = (SVCXPRT *) 0;
  127. if (sock < FD_SETSIZE)
  128. FD_CLR (sock, &svc_fdset);
  129. for (i = 0; i < svc_max_pollfd; ++i)
  130. if (svc_pollfd[i].fd == sock)
  131. svc_pollfd[i].fd = -1;
  132. }
  133. }
  134. #ifdef EXPORT_RPC_SYMBOLS
  135. libc_hidden_def (xprt_unregister)
  136. #else
  137. libc_hidden_nolink_sunrpc (xprt_unregister, GLIBC_2_0)
  138. #endif
  139. /* ********************** CALLOUT list related stuff ************* */
  140. /* Search the callout list for a program number, return the callout
  141. struct. */
  142. static struct svc_callout *
  143. svc_find (rpcprog_t prog, rpcvers_t vers, struct svc_callout **prev)
  144. {
  145. register struct svc_callout *s, *p;
  146. p = NULL_SVC;
  147. for (s = svc_head; s != NULL_SVC; s = s->sc_next)
  148. {
  149. if ((s->sc_prog == prog) && (s->sc_vers == vers))
  150. goto done;
  151. p = s;
  152. }
  153. done:
  154. *prev = p;
  155. return s;
  156. }
  157. /* Add a service program to the callout list.
  158. The dispatch routine will be called when a rpc request for this
  159. program number comes in. */
  160. bool_t
  161. svc_register (SVCXPRT * xprt, rpcprog_t prog, rpcvers_t vers,
  162. void (*dispatch) (struct svc_req *, SVCXPRT *),
  163. rpcproc_t protocol)
  164. {
  165. struct svc_callout *prev;
  166. register struct svc_callout *s;
  167. if ((s = svc_find (prog, vers, &prev)) != NULL_SVC)
  168. {
  169. if (s->sc_dispatch == dispatch)
  170. goto pmap_it; /* he is registering another xptr */
  171. return FALSE;
  172. }
  173. s = (struct svc_callout *) mem_alloc (sizeof (struct svc_callout));
  174. if (s == (struct svc_callout *) 0)
  175. return FALSE;
  176. s->sc_prog = prog;
  177. s->sc_vers = vers;
  178. s->sc_dispatch = dispatch;
  179. s->sc_next = svc_head;
  180. s->sc_mapped = FALSE;
  181. svc_head = s;
  182. pmap_it:
  183. /* now register the information with the local binder service */
  184. if (protocol)
  185. {
  186. if (! pmap_set (prog, vers, protocol, xprt->xp_port))
  187. return FALSE;
  188. s->sc_mapped = TRUE;
  189. }
  190. return TRUE;
  191. }
  192. #ifdef EXPORT_RPC_SYMBOLS
  193. libc_hidden_def (svc_register)
  194. #else
  195. libc_hidden_nolink_sunrpc (svc_register, GLIBC_2_0)
  196. #endif
  197. /* Remove a service program from the callout list. */
  198. void
  199. svc_unregister (rpcprog_t prog, rpcvers_t vers)
  200. {
  201. struct svc_callout *prev;
  202. register struct svc_callout *s;
  203. if ((s = svc_find (prog, vers, &prev)) == NULL_SVC)
  204. return;
  205. bool is_mapped = s->sc_mapped;
  206. if (prev == NULL_SVC)
  207. svc_head = s->sc_next;
  208. else
  209. prev->sc_next = s->sc_next;
  210. s->sc_next = NULL_SVC;
  211. mem_free ((char *) s, (u_int) sizeof (struct svc_callout));
  212. /* now unregister the information with the local binder service */
  213. if (is_mapped)
  214. pmap_unset (prog, vers);
  215. }
  216. libc_hidden_nolink_sunrpc (svc_unregister, GLIBC_2_0)
  217. /* ******************* REPLY GENERATION ROUTINES ************ */
  218. /* Send a reply to an rpc request */
  219. bool_t
  220. svc_sendreply (register SVCXPRT *xprt, xdrproc_t xdr_results,
  221. caddr_t xdr_location)
  222. {
  223. struct rpc_msg rply;
  224. rply.rm_direction = REPLY;
  225. rply.rm_reply.rp_stat = MSG_ACCEPTED;
  226. rply.acpted_rply.ar_verf = xprt->xp_verf;
  227. rply.acpted_rply.ar_stat = SUCCESS;
  228. rply.acpted_rply.ar_results.where = xdr_location;
  229. rply.acpted_rply.ar_results.proc = xdr_results;
  230. return SVC_REPLY (xprt, &rply);
  231. }
  232. #ifdef EXPORT_RPC_SYMBOLS
  233. libc_hidden_def (svc_sendreply)
  234. #else
  235. libc_hidden_nolink_sunrpc (svc_sendreply, GLIBC_2_0)
  236. #endif
  237. /* No procedure error reply */
  238. void
  239. svcerr_noproc (register SVCXPRT *xprt)
  240. {
  241. struct rpc_msg rply;
  242. rply.rm_direction = REPLY;
  243. rply.rm_reply.rp_stat = MSG_ACCEPTED;
  244. rply.acpted_rply.ar_verf = xprt->xp_verf;
  245. rply.acpted_rply.ar_stat = PROC_UNAVAIL;
  246. SVC_REPLY (xprt, &rply);
  247. }
  248. #ifdef EXPORT_RPC_SYMBOLS
  249. libc_hidden_def (svcerr_noproc)
  250. #else
  251. libc_hidden_nolink_sunrpc (svcerr_noproc, GLIBC_2_0)
  252. #endif
  253. /* Can't decode args error reply */
  254. void
  255. svcerr_decode (register SVCXPRT *xprt)
  256. {
  257. struct rpc_msg rply;
  258. rply.rm_direction = REPLY;
  259. rply.rm_reply.rp_stat = MSG_ACCEPTED;
  260. rply.acpted_rply.ar_verf = xprt->xp_verf;
  261. rply.acpted_rply.ar_stat = GARBAGE_ARGS;
  262. SVC_REPLY (xprt, &rply);
  263. }
  264. #ifdef EXPORT_RPC_SYMBOLS
  265. libc_hidden_def (svcerr_decode)
  266. #else
  267. libc_hidden_nolink_sunrpc (svcerr_decode, GLIBC_2_0)
  268. #endif
  269. /* Some system error */
  270. void
  271. svcerr_systemerr (register SVCXPRT *xprt)
  272. {
  273. struct rpc_msg rply;
  274. rply.rm_direction = REPLY;
  275. rply.rm_reply.rp_stat = MSG_ACCEPTED;
  276. rply.acpted_rply.ar_verf = xprt->xp_verf;
  277. rply.acpted_rply.ar_stat = SYSTEM_ERR;
  278. SVC_REPLY (xprt, &rply);
  279. }
  280. #ifdef EXPORT_RPC_SYMBOLS
  281. libc_hidden_def (svcerr_systemerr)
  282. #else
  283. libc_hidden_nolink_sunrpc (svcerr_systemerr, GLIBC_2_0)
  284. #endif
  285. /* Authentication error reply */
  286. void
  287. svcerr_auth (SVCXPRT *xprt, enum auth_stat why)
  288. {
  289. struct rpc_msg rply;
  290. rply.rm_direction = REPLY;
  291. rply.rm_reply.rp_stat = MSG_DENIED;
  292. rply.rjcted_rply.rj_stat = AUTH_ERROR;
  293. rply.rjcted_rply.rj_why = why;
  294. SVC_REPLY (xprt, &rply);
  295. }
  296. libc_hidden_nolink_sunrpc (svcerr_auth, GLIBC_2_0)
  297. /* Auth too weak error reply */
  298. void
  299. svcerr_weakauth (SVCXPRT *xprt)
  300. {
  301. svcerr_auth (xprt, AUTH_TOOWEAK);
  302. }
  303. libc_hidden_nolink_sunrpc (svcerr_weakauth, GLIBC_2_0)
  304. /* Program unavailable error reply */
  305. void
  306. svcerr_noprog (register SVCXPRT *xprt)
  307. {
  308. struct rpc_msg rply;
  309. rply.rm_direction = REPLY;
  310. rply.rm_reply.rp_stat = MSG_ACCEPTED;
  311. rply.acpted_rply.ar_verf = xprt->xp_verf;
  312. rply.acpted_rply.ar_stat = PROG_UNAVAIL;
  313. SVC_REPLY (xprt, &rply);
  314. }
  315. libc_hidden_nolink_sunrpc (svcerr_noprog, GLIBC_2_0)
  316. /* Program version mismatch error reply */
  317. void
  318. svcerr_progvers (register SVCXPRT *xprt, rpcvers_t low_vers,
  319. rpcvers_t high_vers)
  320. {
  321. struct rpc_msg rply;
  322. rply.rm_direction = REPLY;
  323. rply.rm_reply.rp_stat = MSG_ACCEPTED;
  324. rply.acpted_rply.ar_verf = xprt->xp_verf;
  325. rply.acpted_rply.ar_stat = PROG_MISMATCH;
  326. rply.acpted_rply.ar_vers.low = low_vers;
  327. rply.acpted_rply.ar_vers.high = high_vers;
  328. SVC_REPLY (xprt, &rply);
  329. }
  330. libc_hidden_nolink_sunrpc (svcerr_progvers, GLIBC_2_0)
  331. /* ******************* SERVER INPUT STUFF ******************* */
  332. /*
  333. * Get server side input from some transport.
  334. *
  335. * Statement of authentication parameters management:
  336. * This function owns and manages all authentication parameters, specifically
  337. * the "raw" parameters (msg.rm_call.cb_cred and msg.rm_call.cb_verf) and
  338. * the "cooked" credentials (rqst->rq_clntcred).
  339. * However, this function does not know the structure of the cooked
  340. * credentials, so it make the following assumptions:
  341. * a) the structure is contiguous (no pointers), and
  342. * b) the cred structure size does not exceed RQCRED_SIZE bytes.
  343. * In all events, all three parameters are freed upon exit from this routine.
  344. * The storage is trivially management on the call stack in user land, but
  345. * is mallocated in kernel land.
  346. */
  347. void
  348. svc_getreq (int rdfds)
  349. {
  350. fd_set readfds;
  351. FD_ZERO (&readfds);
  352. readfds.fds_bits[0] = rdfds;
  353. svc_getreqset (&readfds);
  354. }
  355. libc_hidden_nolink_sunrpc (svc_getreq, GLIBC_2_0)
  356. void
  357. svc_getreqset (fd_set *readfds)
  358. {
  359. register fd_mask mask;
  360. register fd_mask *maskp;
  361. register int setsize;
  362. register int sock;
  363. register int bit;
  364. setsize = _rpc_dtablesize ();
  365. if (setsize > FD_SETSIZE)
  366. setsize = FD_SETSIZE;
  367. maskp = readfds->fds_bits;
  368. for (sock = 0; sock < setsize; sock += NFDBITS)
  369. for (mask = *maskp++; (bit = ffsl (mask)); mask ^= (1L << (bit - 1)))
  370. svc_getreq_common (sock + bit - 1);
  371. }
  372. libc_hidden_nolink_sunrpc (svc_getreqset, GLIBC_2_0)
  373. void
  374. svc_getreq_poll (struct pollfd *pfdp, int pollretval)
  375. {
  376. if (pollretval == 0)
  377. return;
  378. register int fds_found;
  379. for (int i = fds_found = 0; i < svc_max_pollfd; ++i)
  380. {
  381. register struct pollfd *p = &pfdp[i];
  382. if (p->fd != -1 && p->revents)
  383. {
  384. /* fd has input waiting */
  385. if (p->revents & POLLNVAL)
  386. xprt_unregister (xports[p->fd]);
  387. else
  388. svc_getreq_common (p->fd);
  389. if (++fds_found >= pollretval)
  390. break;
  391. }
  392. }
  393. }
  394. #ifdef EXPORT_RPC_SYMBOLS
  395. libc_hidden_def (svc_getreq_poll)
  396. #else
  397. libc_hidden_nolink_sunrpc (svc_getreq_poll, GLIBC_2_2)
  398. #endif
  399. void
  400. svc_getreq_common (const int fd)
  401. {
  402. enum xprt_stat stat;
  403. struct rpc_msg msg;
  404. register SVCXPRT *xprt;
  405. char cred_area[2 * MAX_AUTH_BYTES + RQCRED_SIZE];
  406. msg.rm_call.cb_cred.oa_base = cred_area;
  407. msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]);
  408. xprt = xports[fd];
  409. /* Do we control fd? */
  410. if (xprt == NULL)
  411. return;
  412. /* now receive msgs from xprtprt (support batch calls) */
  413. do
  414. {
  415. if (SVC_RECV (xprt, &msg))
  416. {
  417. /* now find the exported program and call it */
  418. struct svc_callout *s;
  419. struct svc_req r;
  420. enum auth_stat why;
  421. rpcvers_t low_vers;
  422. rpcvers_t high_vers;
  423. int prog_found;
  424. r.rq_clntcred = &(cred_area[2 * MAX_AUTH_BYTES]);
  425. r.rq_xprt = xprt;
  426. r.rq_prog = msg.rm_call.cb_prog;
  427. r.rq_vers = msg.rm_call.cb_vers;
  428. r.rq_proc = msg.rm_call.cb_proc;
  429. r.rq_cred = msg.rm_call.cb_cred;
  430. /* first authenticate the message */
  431. /* Check for null flavor and bypass these calls if possible */
  432. if (msg.rm_call.cb_cred.oa_flavor == AUTH_NULL)
  433. {
  434. r.rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor;
  435. r.rq_xprt->xp_verf.oa_length = 0;
  436. }
  437. else if ((why = _authenticate (&r, &msg)) != AUTH_OK)
  438. {
  439. svcerr_auth (xprt, why);
  440. goto call_done;
  441. }
  442. /* now match message with a registered service */
  443. prog_found = FALSE;
  444. low_vers = 0 - 1;
  445. high_vers = 0;
  446. for (s = svc_head; s != NULL_SVC; s = s->sc_next)
  447. {
  448. if (s->sc_prog == r.rq_prog)
  449. {
  450. if (s->sc_vers == r.rq_vers)
  451. {
  452. (*s->sc_dispatch) (&r, xprt);
  453. goto call_done;
  454. }
  455. /* found correct version */
  456. prog_found = TRUE;
  457. if (s->sc_vers < low_vers)
  458. low_vers = s->sc_vers;
  459. if (s->sc_vers > high_vers)
  460. high_vers = s->sc_vers;
  461. }
  462. /* found correct program */
  463. }
  464. /* if we got here, the program or version
  465. is not served ... */
  466. if (prog_found)
  467. svcerr_progvers (xprt, low_vers, high_vers);
  468. else
  469. svcerr_noprog (xprt);
  470. /* Fall through to ... */
  471. }
  472. call_done:
  473. if ((stat = SVC_STAT (xprt)) == XPRT_DIED)
  474. {
  475. SVC_DESTROY (xprt);
  476. break;
  477. }
  478. }
  479. while (stat == XPRT_MOREREQS);
  480. }
  481. libc_hidden_nolink_sunrpc (svc_getreq_common, GLIBC_2_2)
  482. /* If there are no file descriptors available, then accept will fail.
  483. We want to delay here so the connection request can be dequeued;
  484. otherwise we can bounce between polling and accepting, never giving the
  485. request a chance to dequeue and eating an enormous amount of cpu time
  486. in svc_run if we're polling on many file descriptors. */
  487. void
  488. __svc_accept_failed (void)
  489. {
  490. if (errno == EMFILE)
  491. {
  492. struct timespec ts = { .tv_sec = 0, .tv_nsec = 50000000 };
  493. __nanosleep (&ts, NULL);
  494. }
  495. }
  496. void
  497. __rpc_thread_svc_cleanup (void)
  498. {
  499. struct svc_callout *svcp;
  500. while ((svcp = svc_head) != NULL)
  501. svc_unregister (svcp->sc_prog, svcp->sc_vers);
  502. }