PageRenderTime 53ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/arm-gp2x-linux-glibc-2.3.6/glibc-2.3.6/sunrpc/svc.c

#
C | 507 lines | 348 code | 68 blank | 91 comment | 67 complexity | d8a236ea03464a0567e912b9f6a1b354 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, BSD-3-Clause, LGPL-2.0
  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. #include <errno.h>
  39. #include <unistd.h>
  40. #include <rpc/rpc.h>
  41. #include <rpc/svc.h>
  42. #include <rpc/pmap_clnt.h>
  43. #include <sys/poll.h>
  44. #ifdef _RPC_THREAD_SAFE_
  45. #define xports RPC_THREAD_VARIABLE(svc_xports_s)
  46. #else
  47. static SVCXPRT **xports;
  48. #endif
  49. #define NULL_SVC ((struct svc_callout *)0)
  50. #define RQCRED_SIZE 400 /* this size is excessive */
  51. /* The services list
  52. Each entry represents a set of procedures (an rpc program).
  53. The dispatch routine takes request structs and runs the
  54. appropriate procedure. */
  55. struct svc_callout {
  56. struct svc_callout *sc_next;
  57. rpcprog_t sc_prog;
  58. rpcvers_t sc_vers;
  59. void (*sc_dispatch) (struct svc_req *, SVCXPRT *);
  60. };
  61. #ifdef _RPC_THREAD_SAFE_
  62. #define svc_head RPC_THREAD_VARIABLE(svc_head_s)
  63. #else
  64. static struct svc_callout *svc_head;
  65. #endif
  66. /* *************** SVCXPRT related stuff **************** */
  67. /* Activate a transport handle. */
  68. void
  69. xprt_register (SVCXPRT *xprt)
  70. {
  71. register int sock = xprt->xp_sock;
  72. register int i;
  73. if (xports == NULL)
  74. {
  75. xports = (SVCXPRT **) malloc (_rpc_dtablesize () * sizeof (SVCXPRT *));
  76. if (xports == NULL) /* DonĀ“t add handle */
  77. return;
  78. }
  79. if (sock < _rpc_dtablesize ())
  80. {
  81. struct pollfd *new_svc_pollfd;
  82. xports[sock] = xprt;
  83. if (sock < FD_SETSIZE)
  84. FD_SET (sock, &svc_fdset);
  85. /* Check if we have an empty slot */
  86. for (i = 0; i < svc_max_pollfd; ++i)
  87. if (svc_pollfd[i].fd == -1)
  88. {
  89. svc_pollfd[i].fd = sock;
  90. svc_pollfd[i].events = (POLLIN | POLLPRI |
  91. POLLRDNORM | POLLRDBAND);
  92. return;
  93. }
  94. new_svc_pollfd = (struct pollfd *) realloc (svc_pollfd,
  95. sizeof (struct pollfd)
  96. * (svc_max_pollfd + 1));
  97. if (new_svc_pollfd == NULL) /* Out of memory */
  98. return;
  99. svc_pollfd = new_svc_pollfd;
  100. ++svc_max_pollfd;
  101. svc_pollfd[svc_max_pollfd - 1].fd = sock;
  102. svc_pollfd[svc_max_pollfd - 1].events = (POLLIN | POLLPRI |
  103. POLLRDNORM | POLLRDBAND);
  104. }
  105. }
  106. libc_hidden_def (xprt_register)
  107. /* De-activate a transport handle. */
  108. void
  109. xprt_unregister (SVCXPRT *xprt)
  110. {
  111. register int sock = xprt->xp_sock;
  112. register int i;
  113. if ((sock < _rpc_dtablesize ()) && (xports[sock] == xprt))
  114. {
  115. xports[sock] = (SVCXPRT *) 0;
  116. if (sock < FD_SETSIZE)
  117. FD_CLR (sock, &svc_fdset);
  118. for (i = 0; i < svc_max_pollfd; ++i)
  119. if (svc_pollfd[i].fd == sock)
  120. svc_pollfd[i].fd = -1;
  121. }
  122. }
  123. libc_hidden_def (xprt_unregister)
  124. /* ********************** CALLOUT list related stuff ************* */
  125. /* Search the callout list for a program number, return the callout
  126. struct. */
  127. static struct svc_callout *
  128. svc_find (rpcprog_t prog, rpcvers_t vers, struct svc_callout **prev)
  129. {
  130. register struct svc_callout *s, *p;
  131. p = NULL_SVC;
  132. for (s = svc_head; s != NULL_SVC; s = s->sc_next)
  133. {
  134. if ((s->sc_prog == prog) && (s->sc_vers == vers))
  135. goto done;
  136. p = s;
  137. }
  138. done:
  139. *prev = p;
  140. return s;
  141. }
  142. /* Add a service program to the callout list.
  143. The dispatch routine will be called when a rpc request for this
  144. program number comes in. */
  145. bool_t
  146. svc_register (SVCXPRT * xprt, rpcprog_t prog, rpcvers_t vers,
  147. void (*dispatch) (struct svc_req *, SVCXPRT *),
  148. rpcproc_t protocol)
  149. {
  150. struct svc_callout *prev;
  151. register struct svc_callout *s;
  152. if ((s = svc_find (prog, vers, &prev)) != NULL_SVC)
  153. {
  154. if (s->sc_dispatch == dispatch)
  155. goto pmap_it; /* he is registering another xptr */
  156. return FALSE;
  157. }
  158. s = (struct svc_callout *) mem_alloc (sizeof (struct svc_callout));
  159. if (s == (struct svc_callout *) 0)
  160. return FALSE;
  161. s->sc_prog = prog;
  162. s->sc_vers = vers;
  163. s->sc_dispatch = dispatch;
  164. s->sc_next = svc_head;
  165. svc_head = s;
  166. pmap_it:
  167. /* now register the information with the local binder service */
  168. if (protocol)
  169. return pmap_set (prog, vers, protocol, xprt->xp_port);
  170. return TRUE;
  171. }
  172. libc_hidden_def (svc_register)
  173. /* Remove a service program from the callout list. */
  174. void
  175. svc_unregister (rpcprog_t prog, rpcvers_t vers)
  176. {
  177. struct svc_callout *prev;
  178. register struct svc_callout *s;
  179. if ((s = svc_find (prog, vers, &prev)) == NULL_SVC)
  180. return;
  181. if (prev == NULL_SVC)
  182. svc_head = s->sc_next;
  183. else
  184. prev->sc_next = s->sc_next;
  185. s->sc_next = NULL_SVC;
  186. mem_free ((char *) s, (u_int) sizeof (struct svc_callout));
  187. /* now unregister the information with the local binder service */
  188. pmap_unset (prog, vers);
  189. }
  190. libc_hidden_def (svc_unregister)
  191. /* ******************* REPLY GENERATION ROUTINES ************ */
  192. /* Send a reply to an rpc request */
  193. bool_t
  194. svc_sendreply (register SVCXPRT *xprt, xdrproc_t xdr_results,
  195. caddr_t xdr_location)
  196. {
  197. struct rpc_msg rply;
  198. rply.rm_direction = REPLY;
  199. rply.rm_reply.rp_stat = MSG_ACCEPTED;
  200. rply.acpted_rply.ar_verf = xprt->xp_verf;
  201. rply.acpted_rply.ar_stat = SUCCESS;
  202. rply.acpted_rply.ar_results.where = xdr_location;
  203. rply.acpted_rply.ar_results.proc = xdr_results;
  204. return SVC_REPLY (xprt, &rply);
  205. }
  206. INTDEF (svc_sendreply)
  207. /* No procedure error reply */
  208. void
  209. svcerr_noproc (register SVCXPRT *xprt)
  210. {
  211. struct rpc_msg rply;
  212. rply.rm_direction = REPLY;
  213. rply.rm_reply.rp_stat = MSG_ACCEPTED;
  214. rply.acpted_rply.ar_verf = xprt->xp_verf;
  215. rply.acpted_rply.ar_stat = PROC_UNAVAIL;
  216. SVC_REPLY (xprt, &rply);
  217. }
  218. /* Can't decode args error reply */
  219. void
  220. svcerr_decode (register SVCXPRT *xprt)
  221. {
  222. struct rpc_msg rply;
  223. rply.rm_direction = REPLY;
  224. rply.rm_reply.rp_stat = MSG_ACCEPTED;
  225. rply.acpted_rply.ar_verf = xprt->xp_verf;
  226. rply.acpted_rply.ar_stat = GARBAGE_ARGS;
  227. SVC_REPLY (xprt, &rply);
  228. }
  229. INTDEF (svcerr_decode)
  230. /* Some system error */
  231. void
  232. svcerr_systemerr (register SVCXPRT *xprt)
  233. {
  234. struct rpc_msg rply;
  235. rply.rm_direction = REPLY;
  236. rply.rm_reply.rp_stat = MSG_ACCEPTED;
  237. rply.acpted_rply.ar_verf = xprt->xp_verf;
  238. rply.acpted_rply.ar_stat = SYSTEM_ERR;
  239. SVC_REPLY (xprt, &rply);
  240. }
  241. /* Authentication error reply */
  242. void
  243. svcerr_auth (SVCXPRT *xprt, enum auth_stat why)
  244. {
  245. struct rpc_msg rply;
  246. rply.rm_direction = REPLY;
  247. rply.rm_reply.rp_stat = MSG_DENIED;
  248. rply.rjcted_rply.rj_stat = AUTH_ERROR;
  249. rply.rjcted_rply.rj_why = why;
  250. SVC_REPLY (xprt, &rply);
  251. }
  252. libc_hidden_def (svcerr_auth)
  253. /* Auth too weak error reply */
  254. void
  255. svcerr_weakauth (SVCXPRT *xprt)
  256. {
  257. svcerr_auth (xprt, AUTH_TOOWEAK);
  258. }
  259. /* Program unavailable error reply */
  260. void
  261. svcerr_noprog (register SVCXPRT *xprt)
  262. {
  263. struct rpc_msg rply;
  264. rply.rm_direction = REPLY;
  265. rply.rm_reply.rp_stat = MSG_ACCEPTED;
  266. rply.acpted_rply.ar_verf = xprt->xp_verf;
  267. rply.acpted_rply.ar_stat = PROG_UNAVAIL;
  268. SVC_REPLY (xprt, &rply);
  269. }
  270. libc_hidden_def (svcerr_noprog)
  271. /* Program version mismatch error reply */
  272. void
  273. svcerr_progvers (register SVCXPRT *xprt, rpcvers_t low_vers,
  274. rpcvers_t high_vers)
  275. {
  276. struct rpc_msg rply;
  277. rply.rm_direction = REPLY;
  278. rply.rm_reply.rp_stat = MSG_ACCEPTED;
  279. rply.acpted_rply.ar_verf = xprt->xp_verf;
  280. rply.acpted_rply.ar_stat = PROG_MISMATCH;
  281. rply.acpted_rply.ar_vers.low = low_vers;
  282. rply.acpted_rply.ar_vers.high = high_vers;
  283. SVC_REPLY (xprt, &rply);
  284. }
  285. libc_hidden_def (svcerr_progvers)
  286. /* ******************* SERVER INPUT STUFF ******************* */
  287. /*
  288. * Get server side input from some transport.
  289. *
  290. * Statement of authentication parameters management:
  291. * This function owns and manages all authentication parameters, specifically
  292. * the "raw" parameters (msg.rm_call.cb_cred and msg.rm_call.cb_verf) and
  293. * the "cooked" credentials (rqst->rq_clntcred).
  294. * However, this function does not know the structure of the cooked
  295. * credentials, so it make the following assumptions:
  296. * a) the structure is contiguous (no pointers), and
  297. * b) the cred structure size does not exceed RQCRED_SIZE bytes.
  298. * In all events, all three parameters are freed upon exit from this routine.
  299. * The storage is trivially management on the call stack in user land, but
  300. * is mallocated in kernel land.
  301. */
  302. void
  303. svc_getreq (int rdfds)
  304. {
  305. fd_set readfds;
  306. FD_ZERO (&readfds);
  307. readfds.fds_bits[0] = rdfds;
  308. INTUSE(svc_getreqset) (&readfds);
  309. }
  310. INTDEF (svc_getreq)
  311. void
  312. svc_getreqset (fd_set *readfds)
  313. {
  314. register fd_mask mask;
  315. register fd_mask *maskp;
  316. register int setsize;
  317. register int sock;
  318. register int bit;
  319. setsize = _rpc_dtablesize ();
  320. if (setsize > FD_SETSIZE)
  321. setsize = FD_SETSIZE;
  322. maskp = readfds->fds_bits;
  323. for (sock = 0; sock < setsize; sock += NFDBITS)
  324. for (mask = *maskp++; (bit = ffs (mask)); mask ^= (1 << (bit - 1)))
  325. INTUSE(svc_getreq_common) (sock + bit - 1);
  326. }
  327. INTDEF (svc_getreqset)
  328. void
  329. svc_getreq_poll (struct pollfd *pfdp, int pollretval)
  330. {
  331. register int i;
  332. register int fds_found;
  333. for (i = fds_found = 0; i < svc_max_pollfd && fds_found < pollretval; ++i)
  334. {
  335. register struct pollfd *p = &pfdp[i];
  336. if (p->fd != -1 && p->revents)
  337. {
  338. /* fd has input waiting */
  339. ++fds_found;
  340. if (p->revents & POLLNVAL)
  341. xprt_unregister (xports[p->fd]);
  342. else
  343. INTUSE(svc_getreq_common) (p->fd);
  344. }
  345. }
  346. }
  347. INTDEF (svc_getreq_poll)
  348. void
  349. svc_getreq_common (const int fd)
  350. {
  351. enum xprt_stat stat;
  352. struct rpc_msg msg;
  353. register SVCXPRT *xprt;
  354. char cred_area[2 * MAX_AUTH_BYTES + RQCRED_SIZE];
  355. msg.rm_call.cb_cred.oa_base = cred_area;
  356. msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]);
  357. xprt = xports[fd];
  358. /* Do we control fd? */
  359. if (xprt == NULL)
  360. return;
  361. /* now receive msgs from xprtprt (support batch calls) */
  362. do
  363. {
  364. if (SVC_RECV (xprt, &msg))
  365. {
  366. /* now find the exported program and call it */
  367. struct svc_callout *s;
  368. struct svc_req r;
  369. enum auth_stat why;
  370. rpcvers_t low_vers;
  371. rpcvers_t high_vers;
  372. int prog_found;
  373. r.rq_clntcred = &(cred_area[2 * MAX_AUTH_BYTES]);
  374. r.rq_xprt = xprt;
  375. r.rq_prog = msg.rm_call.cb_prog;
  376. r.rq_vers = msg.rm_call.cb_vers;
  377. r.rq_proc = msg.rm_call.cb_proc;
  378. r.rq_cred = msg.rm_call.cb_cred;
  379. /* first authenticate the message */
  380. /* Check for null flavor and bypass these calls if possible */
  381. if (msg.rm_call.cb_cred.oa_flavor == AUTH_NULL)
  382. {
  383. r.rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor;
  384. r.rq_xprt->xp_verf.oa_length = 0;
  385. }
  386. else if ((why = INTUSE(_authenticate) (&r, &msg)) != AUTH_OK)
  387. {
  388. svcerr_auth (xprt, why);
  389. goto call_done;
  390. }
  391. /* now match message with a registered service */
  392. prog_found = FALSE;
  393. low_vers = 0 - 1;
  394. high_vers = 0;
  395. for (s = svc_head; s != NULL_SVC; s = s->sc_next)
  396. {
  397. if (s->sc_prog == r.rq_prog)
  398. {
  399. if (s->sc_vers == r.rq_vers)
  400. {
  401. (*s->sc_dispatch) (&r, xprt);
  402. goto call_done;
  403. }
  404. /* found correct version */
  405. prog_found = TRUE;
  406. if (s->sc_vers < low_vers)
  407. low_vers = s->sc_vers;
  408. if (s->sc_vers > high_vers)
  409. high_vers = s->sc_vers;
  410. }
  411. /* found correct program */
  412. }
  413. /* if we got here, the program or version
  414. is not served ... */
  415. if (prog_found)
  416. svcerr_progvers (xprt, low_vers, high_vers);
  417. else
  418. svcerr_noprog (xprt);
  419. /* Fall through to ... */
  420. }
  421. call_done:
  422. if ((stat = SVC_STAT (xprt)) == XPRT_DIED)
  423. {
  424. SVC_DESTROY (xprt);
  425. break;
  426. }
  427. }
  428. while (stat == XPRT_MOREREQS);
  429. }
  430. INTDEF (svc_getreq_common)
  431. #ifdef _RPC_THREAD_SAFE_
  432. void
  433. __rpc_thread_svc_cleanup (void)
  434. {
  435. struct svc_callout *svcp;
  436. while ((svcp = svc_head) != NULL)
  437. svc_unregister (svcp->sc_prog, svcp->sc_vers);
  438. }
  439. #endif /* _RPC_THREAD_SAFE_ */