svc.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514
  1. /*
  2. * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  3. * unrestricted use provided that this legend is included on all tape
  4. * media and as a part of the software program in whole or part. Users
  5. * may copy or modify Sun RPC without charge, but are not authorized
  6. * to license or distribute it to anyone else except as part of a product or
  7. * program developed by the user.
  8. *
  9. * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  10. * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  11. * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  12. *
  13. * Sun RPC is provided with no support and without any obligation on the
  14. * part of Sun Microsystems, Inc. to assist in its use, correction,
  15. * modification or enhancement.
  16. *
  17. * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  18. * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  19. * OR ANY PART THEREOF.
  20. *
  21. * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  22. * or profits or other special, indirect and consequential damages, even if
  23. * Sun has been advised of the possibility of such damages.
  24. *
  25. * Sun Microsystems, Inc.
  26. * 2550 Garcia Avenue
  27. * Mountain View, California 94043
  28. */
  29. /*
  30. * svc.c, Server-side remote procedure call interface.
  31. *
  32. * There are two sets of procedures here. The xprt routines are
  33. * for handling transport handles. The svc routines handle the
  34. * list of service routines.
  35. *
  36. * Copyright (C) 1984, Sun Microsystems, Inc.
  37. */
  38. #define ffs __ffs
  39. #define pmap_set __pmap_set
  40. #define pmap_unset __pmap_unset
  41. #define _authenticate _authenticate_internal
  42. #define _rpc_dtablesize _rpc_dtablesize_internal
  43. /* used by svc_[max_]pollfd */
  44. #define __rpc_thread_svc_pollfd __rpc_thread_svc_pollfd_internal
  45. #define __rpc_thread_svc_max_pollfd __rpc_thread_svc_max_pollfd_internal
  46. /* used by svc_fdset */
  47. #define __rpc_thread_svc_fdset __rpc_thread_svc_fdset_internal
  48. #define __FORCE_GLIBC
  49. #define _GNU_SOURCE
  50. #include <features.h>
  51. #include <errno.h>
  52. #include <unistd.h>
  53. #include "rpc_private.h"
  54. #include <rpc/svc.h>
  55. #include <rpc/pmap_clnt.h>
  56. #include <sys/poll.h>
  57. #ifdef __UCLIBC_HAS_THREADS__
  58. #define xports (*(SVCXPRT ***)&RPC_THREAD_VARIABLE(svc_xports_s))
  59. #else
  60. static SVCXPRT **xports;
  61. #endif
  62. #define NULL_SVC ((struct svc_callout *)0)
  63. #define RQCRED_SIZE 400 /* this size is excessive */
  64. /* The services list
  65. Each entry represents a set of procedures (an rpc program).
  66. The dispatch routine takes request structs and runs the
  67. appropriate procedure. */
  68. struct svc_callout {
  69. struct svc_callout *sc_next;
  70. rpcprog_t sc_prog;
  71. rpcvers_t sc_vers;
  72. void (*sc_dispatch) (struct svc_req *, SVCXPRT *);
  73. };
  74. #ifdef __UCLIBC_HAS_THREADS__
  75. #define svc_head (*(struct svc_callout **)&RPC_THREAD_VARIABLE(svc_head_s))
  76. #else
  77. static struct svc_callout *svc_head;
  78. #endif
  79. /* *************** SVCXPRT related stuff **************** */
  80. /* Activate a transport handle. */
  81. void attribute_hidden
  82. __xprt_register (SVCXPRT *xprt)
  83. {
  84. register int sock = xprt->xp_sock;
  85. register int i;
  86. if (xports == NULL)
  87. {
  88. xports = (SVCXPRT **) malloc (_rpc_dtablesize () * sizeof (SVCXPRT *));
  89. if (xports == NULL) /* Don´t add handle */
  90. return;
  91. }
  92. if (sock < _rpc_dtablesize ())
  93. {
  94. xports[sock] = xprt;
  95. if (sock < FD_SETSIZE)
  96. FD_SET (sock, &svc_fdset);
  97. /* Check if we have an empty slot */
  98. for (i = 0; i < svc_max_pollfd; ++i)
  99. if (svc_pollfd[i].fd == -1)
  100. {
  101. svc_pollfd[i].fd = sock;
  102. svc_pollfd[i].events = (POLLIN | POLLPRI |
  103. POLLRDNORM | POLLRDBAND);
  104. return;
  105. }
  106. ++svc_max_pollfd;
  107. svc_pollfd = realloc (svc_pollfd,
  108. sizeof (struct pollfd) * svc_max_pollfd);
  109. if (svc_pollfd == NULL) /* Out of memory */
  110. return;
  111. svc_pollfd[svc_max_pollfd - 1].fd = sock;
  112. svc_pollfd[svc_max_pollfd - 1].events = (POLLIN | POLLPRI |
  113. POLLRDNORM | POLLRDBAND);
  114. }
  115. }
  116. strong_alias(__xprt_register,xprt_register)
  117. /* De-activate a transport handle. */
  118. void attribute_hidden
  119. __xprt_unregister (SVCXPRT *xprt)
  120. {
  121. register int sock = xprt->xp_sock;
  122. register int i;
  123. if ((sock < _rpc_dtablesize ()) && (xports[sock] == xprt))
  124. {
  125. xports[sock] = (SVCXPRT *) 0;
  126. if (sock < FD_SETSIZE)
  127. FD_CLR (sock, &svc_fdset);
  128. for (i = 0; i < svc_max_pollfd; ++i)
  129. if (svc_pollfd[i].fd == sock)
  130. svc_pollfd[i].fd = -1;
  131. }
  132. }
  133. strong_alias(__xprt_unregister,xprt_unregister)
  134. /* ********************** CALLOUT list related stuff ************* */
  135. /* Search the callout list for a program number, return the callout
  136. struct. */
  137. static struct svc_callout *
  138. svc_find (rpcprog_t prog, rpcvers_t vers, struct svc_callout **prev)
  139. {
  140. register struct svc_callout *s, *p;
  141. p = NULL_SVC;
  142. for (s = svc_head; s != NULL_SVC; s = s->sc_next)
  143. {
  144. if ((s->sc_prog == prog) && (s->sc_vers == vers))
  145. goto done;
  146. p = s;
  147. }
  148. done:
  149. *prev = p;
  150. return s;
  151. }
  152. /* Add a service program to the callout list.
  153. The dispatch routine will be called when a rpc request for this
  154. program number comes in. */
  155. bool_t attribute_hidden
  156. __svc_register (SVCXPRT * xprt, rpcprog_t prog, rpcvers_t vers,
  157. void (*dispatch) (struct svc_req *, SVCXPRT *),
  158. rpcproc_t protocol)
  159. {
  160. struct svc_callout *prev;
  161. register struct svc_callout *s;
  162. if ((s = svc_find (prog, vers, &prev)) != NULL_SVC)
  163. {
  164. if (s->sc_dispatch == dispatch)
  165. goto pmap_it; /* he is registering another xptr */
  166. return FALSE;
  167. }
  168. s = (struct svc_callout *) mem_alloc (sizeof (struct svc_callout));
  169. if (s == (struct svc_callout *) 0)
  170. return FALSE;
  171. s->sc_prog = prog;
  172. s->sc_vers = vers;
  173. s->sc_dispatch = dispatch;
  174. s->sc_next = svc_head;
  175. svc_head = s;
  176. pmap_it:
  177. /* now register the information with the local binder service */
  178. if (protocol)
  179. return pmap_set (prog, vers, protocol, xprt->xp_port);
  180. return TRUE;
  181. }
  182. strong_alias(__svc_register,svc_register)
  183. /* Remove a service program from the callout list. */
  184. void attribute_hidden
  185. __svc_unregister (rpcprog_t prog, rpcvers_t vers)
  186. {
  187. struct svc_callout *prev;
  188. register struct svc_callout *s;
  189. if ((s = svc_find (prog, vers, &prev)) == NULL_SVC)
  190. return;
  191. if (prev == NULL_SVC)
  192. svc_head = s->sc_next;
  193. else
  194. prev->sc_next = s->sc_next;
  195. s->sc_next = NULL_SVC;
  196. mem_free ((char *) s, (u_int) sizeof (struct svc_callout));
  197. /* now unregister the information with the local binder service */
  198. pmap_unset (prog, vers);
  199. }
  200. strong_alias(__svc_unregister,svc_unregister)
  201. /* ******************* REPLY GENERATION ROUTINES ************ */
  202. /* Send a reply to an rpc request */
  203. bool_t attribute_hidden
  204. __svc_sendreply (register SVCXPRT *xprt, xdrproc_t xdr_results,
  205. caddr_t xdr_location)
  206. {
  207. struct rpc_msg rply;
  208. rply.rm_direction = REPLY;
  209. rply.rm_reply.rp_stat = MSG_ACCEPTED;
  210. rply.acpted_rply.ar_verf = xprt->xp_verf;
  211. rply.acpted_rply.ar_stat = SUCCESS;
  212. rply.acpted_rply.ar_results.where = xdr_location;
  213. rply.acpted_rply.ar_results.proc = xdr_results;
  214. return SVC_REPLY (xprt, &rply);
  215. }
  216. strong_alias(__svc_sendreply,svc_sendreply)
  217. /* No procedure error reply */
  218. void
  219. svcerr_noproc (register SVCXPRT *xprt)
  220. {
  221. struct rpc_msg rply;
  222. rply.rm_direction = REPLY;
  223. rply.rm_reply.rp_stat = MSG_ACCEPTED;
  224. rply.acpted_rply.ar_verf = xprt->xp_verf;
  225. rply.acpted_rply.ar_stat = PROC_UNAVAIL;
  226. SVC_REPLY (xprt, &rply);
  227. }
  228. /* Can't decode args error reply */
  229. void attribute_hidden
  230. __svcerr_decode (register SVCXPRT *xprt)
  231. {
  232. struct rpc_msg rply;
  233. rply.rm_direction = REPLY;
  234. rply.rm_reply.rp_stat = MSG_ACCEPTED;
  235. rply.acpted_rply.ar_verf = xprt->xp_verf;
  236. rply.acpted_rply.ar_stat = GARBAGE_ARGS;
  237. SVC_REPLY (xprt, &rply);
  238. }
  239. strong_alias(__svcerr_decode,svcerr_decode)
  240. /* Some system error */
  241. void
  242. svcerr_systemerr (register SVCXPRT *xprt)
  243. {
  244. struct rpc_msg rply;
  245. rply.rm_direction = REPLY;
  246. rply.rm_reply.rp_stat = MSG_ACCEPTED;
  247. rply.acpted_rply.ar_verf = xprt->xp_verf;
  248. rply.acpted_rply.ar_stat = SYSTEM_ERR;
  249. SVC_REPLY (xprt, &rply);
  250. }
  251. /* Authentication error reply */
  252. void attribute_hidden
  253. __svcerr_auth (SVCXPRT *xprt, enum auth_stat why)
  254. {
  255. struct rpc_msg rply;
  256. rply.rm_direction = REPLY;
  257. rply.rm_reply.rp_stat = MSG_DENIED;
  258. rply.rjcted_rply.rj_stat = AUTH_ERROR;
  259. rply.rjcted_rply.rj_why = why;
  260. SVC_REPLY (xprt, &rply);
  261. }
  262. strong_alias(__svcerr_auth,svcerr_auth)
  263. /* Auth too weak error reply */
  264. void
  265. svcerr_weakauth (SVCXPRT *xprt)
  266. {
  267. __svcerr_auth (xprt, AUTH_TOOWEAK);
  268. }
  269. /* Program unavailable error reply */
  270. void attribute_hidden
  271. __svcerr_noprog (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 = PROG_UNAVAIL;
  278. SVC_REPLY (xprt, &rply);
  279. }
  280. strong_alias(__svcerr_noprog,svcerr_noprog)
  281. /* Program version mismatch error reply */
  282. void attribute_hidden
  283. __svcerr_progvers (register SVCXPRT *xprt, rpcvers_t low_vers,
  284. rpcvers_t high_vers)
  285. {
  286. struct rpc_msg rply;
  287. rply.rm_direction = REPLY;
  288. rply.rm_reply.rp_stat = MSG_ACCEPTED;
  289. rply.acpted_rply.ar_verf = xprt->xp_verf;
  290. rply.acpted_rply.ar_stat = PROG_MISMATCH;
  291. rply.acpted_rply.ar_vers.low = low_vers;
  292. rply.acpted_rply.ar_vers.high = high_vers;
  293. SVC_REPLY (xprt, &rply);
  294. }
  295. strong_alias(__svcerr_progvers,svcerr_progvers)
  296. /* ******************* SERVER INPUT STUFF ******************* */
  297. /*
  298. * Get server side input from some transport.
  299. *
  300. * Statement of authentication parameters management:
  301. * This function owns and manages all authentication parameters, specifically
  302. * the "raw" parameters (msg.rm_call.cb_cred and msg.rm_call.cb_verf) and
  303. * the "cooked" credentials (rqst->rq_clntcred).
  304. * However, this function does not know the structure of the cooked
  305. * credentials, so it make the following assumptions:
  306. * a) the structure is contiguous (no pointers), and
  307. * b) the cred structure size does not exceed RQCRED_SIZE bytes.
  308. * In all events, all three parameters are freed upon exit from this routine.
  309. * The storage is trivially management on the call stack in user land, but
  310. * is mallocated in kernel land.
  311. */
  312. void attribute_hidden
  313. __svc_getreq_common (const int fd)
  314. {
  315. enum xprt_stat stat;
  316. struct rpc_msg msg;
  317. register SVCXPRT *xprt;
  318. char cred_area[2 * MAX_AUTH_BYTES + RQCRED_SIZE];
  319. msg.rm_call.cb_cred.oa_base = cred_area;
  320. msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]);
  321. xprt = xports[fd];
  322. /* Do we control fd? */
  323. if (xprt == NULL)
  324. return;
  325. /* now receive msgs from xprtprt (support batch calls) */
  326. do
  327. {
  328. if (SVC_RECV (xprt, &msg))
  329. {
  330. /* now find the exported program and call it */
  331. struct svc_callout *s;
  332. struct svc_req r;
  333. enum auth_stat why;
  334. rpcvers_t low_vers;
  335. rpcvers_t high_vers;
  336. int prog_found;
  337. r.rq_clntcred = &(cred_area[2 * MAX_AUTH_BYTES]);
  338. r.rq_xprt = xprt;
  339. r.rq_prog = msg.rm_call.cb_prog;
  340. r.rq_vers = msg.rm_call.cb_vers;
  341. r.rq_proc = msg.rm_call.cb_proc;
  342. r.rq_cred = msg.rm_call.cb_cred;
  343. /* first authenticate the message */
  344. /* Check for null flavor and bypass these calls if possible */
  345. if (msg.rm_call.cb_cred.oa_flavor == AUTH_NULL)
  346. {
  347. r.rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor;
  348. r.rq_xprt->xp_verf.oa_length = 0;
  349. }
  350. else if ((why = _authenticate (&r, &msg)) != AUTH_OK)
  351. {
  352. __svcerr_auth (xprt, why);
  353. goto call_done;
  354. }
  355. /* now match message with a registered service */
  356. prog_found = FALSE;
  357. low_vers = 0 - 1;
  358. high_vers = 0;
  359. for (s = svc_head; s != NULL_SVC; s = s->sc_next)
  360. {
  361. if (s->sc_prog == r.rq_prog)
  362. {
  363. if (s->sc_vers == r.rq_vers)
  364. {
  365. (*s->sc_dispatch) (&r, xprt);
  366. goto call_done;
  367. }
  368. /* found correct version */
  369. prog_found = TRUE;
  370. if (s->sc_vers < low_vers)
  371. low_vers = s->sc_vers;
  372. if (s->sc_vers > high_vers)
  373. high_vers = s->sc_vers;
  374. }
  375. /* found correct program */
  376. }
  377. /* if we got here, the program or version
  378. is not served ... */
  379. if (prog_found)
  380. __svcerr_progvers (xprt, low_vers, high_vers);
  381. else
  382. __svcerr_noprog (xprt);
  383. /* Fall through to ... */
  384. }
  385. call_done:
  386. if ((stat = SVC_STAT (xprt)) == XPRT_DIED)
  387. {
  388. SVC_DESTROY (xprt);
  389. break;
  390. }
  391. }
  392. while (stat == XPRT_MOREREQS);
  393. }
  394. strong_alias(__svc_getreq_common,svc_getreq_common)
  395. void attribute_hidden
  396. __svc_getreqset (fd_set *readfds)
  397. {
  398. register u_int32_t mask;
  399. register u_int32_t *maskp;
  400. register int setsize;
  401. register int sock;
  402. register int bit;
  403. setsize = _rpc_dtablesize ();
  404. maskp = (u_int32_t *) readfds->fds_bits;
  405. for (sock = 0; sock < setsize; sock += 32)
  406. for (mask = *maskp++; (bit = ffs (mask)); mask ^= (1 << (bit - 1)))
  407. __svc_getreq_common (sock + bit - 1);
  408. }
  409. strong_alias(__svc_getreqset,svc_getreqset)
  410. void attribute_hidden
  411. __svc_getreq (int rdfds)
  412. {
  413. fd_set readfds;
  414. FD_ZERO (&readfds);
  415. readfds.fds_bits[0] = rdfds;
  416. __svc_getreqset (&readfds);
  417. }
  418. strong_alias(__svc_getreq,svc_getreq)
  419. void attribute_hidden
  420. __svc_getreq_poll (struct pollfd *pfdp, int pollretval)
  421. {
  422. register int i;
  423. register int fds_found;
  424. for (i = fds_found = 0; i < svc_max_pollfd && fds_found < pollretval; ++i)
  425. {
  426. register struct pollfd *p = &pfdp[i];
  427. if (p->fd != -1 && p->revents)
  428. {
  429. /* fd has input waiting */
  430. ++fds_found;
  431. if (p->revents & POLLNVAL)
  432. __xprt_unregister (xports[p->fd]);
  433. else
  434. __svc_getreq_common (p->fd);
  435. }
  436. }
  437. }
  438. strong_alias(__svc_getreq_poll,svc_getreq_poll)
  439. #ifdef __UCLIBC_HAS_THREADS__
  440. void attribute_hidden __rpc_thread_svc_cleanup (void)
  441. {
  442. struct svc_callout *svcp;
  443. while ((svcp = svc_head) != NULL)
  444. __svc_unregister (svcp->sc_prog, svcp->sc_vers);
  445. }
  446. #endif /* __UCLIBC_HAS_THREADS__ */