svc.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:13k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* svc.c - server-side remote procedure call interface */
  2. /* Copyright 1984-2000 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5.  * Copyright (C) 1984, Sun Microsystems, Inc.
  6.  *
  7.  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  8.  * unrestricted use provided that this legend is included on all tape
  9.  * media and as a part of the software program in whole or part.  Users
  10.  * may copy or modify Sun RPC without charge, but are not authorized
  11.  * to license or distribute it to anyone else except as part of a product or
  12.  * program developed by the user.
  13.  *
  14.  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  15.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  16.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  17.  *
  18.  * Sun RPC is provided with no support and without any obligation on the
  19.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  20.  * modification or enhancement.
  21.  *
  22.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  23.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  24.  * OR ANY PART THEREOF.
  25.  *
  26.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  27.  * or profits or other special, indirect and consequential damages, even if
  28.  * Sun has been advised of the possibility of such damages.
  29.  *
  30.  * Sun Microsystems, Inc.
  31.  * 2550 Garcia Avenue
  32.  * Mountain View, California  94043
  33.  */
  34. /*
  35. modification history
  36. --------------------
  37. 01q,15oct01,rae  merge from truestack ver 01r, base 01p (AE / 5_X)
  38. 01p,12oct94,ism  Added Chris Ford's symptom fix for SPR#3269 (more to come)
  39. 01o,26may92,rrr  the tree shuffle
  40.   -changed includes to have absolute path from h/
  41. 01n,04oct91,rrr  passed through the ansification filter
  42.   -changed includes to have absolute path from h/
  43.   -changed copyright notice
  44. 01m,25oct90,dnw  removed include of utime.h.
  45. 01l,10may90,dnw  moved moduleStatics to rpcGbl; removed init/exit routines
  46.  changed taskModuleList to taskRpcStatics
  47.  changed to use rpcErrnoGet instead of errnoGet
  48. 01k,11may90,yao  added missing modification history (01j) for the last checkin.
  49. 01j,09may90,yao  typecasted malloc to (char *).
  50. 01i,19apr90,hjb   de-linted.
  51. 01h,27oct89,hjb   upgraded to 4.0
  52. 01g,19arp89,gae   added svcExit to do tidy cleanup for tasks.
  53.   changed svcInit to return pointer to moduleStatics.
  54. 01f,30may88,dnw   changed to v4 names.
  55. 01e,25apr88,gae   oops! forgot name change in svc_run().
  56. 01d,23apr88,gae   fixed svc_getreq()/svc_getreqset().
  57. 01c,05apr88,gae   updated select() to BSD4.3, i.e. used "fd_set".
  58. 01b,11nov87,jlf   added wrs copyright, title, mod history, etc.
  59. 01a,01nov87,rdc   first VxWorks version
  60. */
  61. #ifndef lint
  62. /* static char sccsid[] = "@(#)svc.c 1.1 86/02/03 Copyr 1984 Sun Micro"; */
  63. #endif
  64. /*
  65.  * svc.c, Server-side remote procedure call interface.
  66.  *
  67.  * There are two sets of procedures here.  The xprt routines are
  68.  * for handling transport handles.  The svc routines handle the
  69.  * list of service routines.
  70.  *
  71.  */
  72. #include "rpc/rpctypes.h"
  73. #include "errno.h"
  74. #include "netinet/in.h"
  75. #include "rpc/xdr.h"
  76. #include "rpc/auth.h"
  77. #include "rpc/clnt.h"
  78. #include "rpc/rpc_msg.h"
  79. #include "rpc/svc.h"
  80. #include "rpc/svc_auth.h"
  81. #include "rpc/pmap_clnt.h"
  82. #include "vxWorks.h"
  83. #include "memLib.h"
  84. #include "rpc/rpcGbl.h"
  85. #include "memPartLib.h"
  86. #include "rpcLib.h"
  87. #include "stdio.h"
  88. #define NULL_SVC ((struct svc_callout *)0)
  89. #define RQCRED_SIZE 400
  90. struct svc_callout *svc_find();
  91. /* ***************  SVCXPRT related stuff **************** */
  92. /*
  93.  * Activate a transport handle.
  94.  */
  95. void
  96. xprt_register(xprt)
  97. SVCXPRT *xprt;
  98. {
  99. register int sock = xprt->xp_sock;
  100. FAST struct svc *ms = &taskRpcStatics->svc;
  101. if (sock < FD_SETSIZE) {
  102. ms->xports[sock] = xprt;
  103. FD_SET(sock, &ms->svc_fdset);
  104. }
  105. }
  106. /*
  107.  * De-activate a transport handle.
  108.  */
  109. void
  110. xprt_unregister(xprt)
  111. SVCXPRT *xprt;
  112. {
  113. register int sock = xprt->xp_sock;
  114. FAST struct svc *ms = &taskRpcStatics->svc;
  115. if (taskRpcStatics == 0x0)
  116.         return;
  117. if ((sock < FD_SETSIZE) && (ms->xports[sock] == xprt)) {
  118. ms->xports[sock] = (SVCXPRT *)0;
  119. FD_CLR(sock, &ms->svc_fdset);
  120. }
  121. }
  122. /* ********************** CALLOUT list related stuff ************* */
  123. /*
  124.  * Add a service program to the callout list.
  125.  * The dispatch routine will be called when a rpc request for this
  126.  * program number comes in.
  127.  */
  128. bool_t
  129. svc_register(xprt, prog, vers, dispatch, protocol)
  130. SVCXPRT *xprt;
  131. u_long prog;
  132. u_long vers;
  133. void (*dispatch)();
  134. int protocol;
  135. {
  136. struct svc_callout *prev;
  137. register struct svc_callout *s;
  138. FAST struct svc *ms = &taskRpcStatics->svc;
  139. if ((s = svc_find(prog, vers, &prev)) != NULL_SVC) {
  140. if (s->sc_dispatch == dispatch)
  141. goto pmap_it;  /* he is registering another xptr */
  142. return (FALSE);
  143. }
  144. s = (struct svc_callout *)mem_alloc(sizeof(struct svc_callout));
  145. if (s == (struct svc_callout *)0) {
  146. return (FALSE);
  147. }
  148. s->sc_prog = prog;
  149. s->sc_vers = vers;
  150. s->sc_dispatch = dispatch;
  151. s->sc_next = ms->svc_head;
  152. ms->svc_head = s;
  153. pmap_it:
  154. /* now register the information with the local binder service */
  155. if (protocol) {
  156. return (pmap_set(prog, vers, (u_long) protocol, xprt->xp_port));
  157. }
  158. return (TRUE);
  159. }
  160. /*
  161.  * Remove a service program from the callout list.
  162.  */
  163. void
  164. svc_unregister(prog, vers)
  165. u_long prog;
  166. u_long vers;
  167. {
  168. struct svc_callout *prev;
  169. register struct svc_callout *s;
  170. FAST struct svc *ms = &taskRpcStatics->svc;
  171. if ((s = svc_find(prog, vers, &prev)) == NULL_SVC)
  172. return;
  173. if (prev == NULL_SVC) {
  174. ms->svc_head = s->sc_next;
  175. } else {
  176. prev->sc_next = s->sc_next;
  177. }
  178. s->sc_next = NULL_SVC;
  179. mem_free((char *) s, (u_int) sizeof(struct svc_callout));
  180. /* now unregister the information with the local binder service */
  181. (void)pmap_unset(prog, vers);
  182. }
  183. /*
  184.  * Search the callout list for a program number, return the callout
  185.  * struct.
  186.  */
  187. struct svc_callout *
  188. svc_find(prog, vers, prev)
  189. u_long prog;
  190. u_long vers;
  191. struct svc_callout **prev;
  192. {
  193. register struct svc_callout *s, *p;
  194. FAST struct svc *ms = &taskRpcStatics->svc;
  195. p = NULL_SVC;
  196. for (s = ms->svc_head; s != NULL_SVC; s = s->sc_next) {
  197. if ((s->sc_prog == prog) && (s->sc_vers == vers))
  198. goto done;
  199. p = s;
  200. }
  201. done:
  202. *prev = p;
  203. return (s);
  204. }
  205. /* ******************* REPLY GENERATION ROUTINES  ************ */
  206. /*
  207.  * Send a reply to an rpc request
  208.  */
  209. bool_t
  210. svc_sendreply(xprt, xdr_results, xdr_location)
  211. register SVCXPRT *xprt;
  212. xdrproc_t xdr_results;
  213. caddr_t xdr_location;
  214. {
  215. struct rpc_msg rply;
  216. rply.rm_direction = REPLY;
  217. rply.rm_reply.rp_stat = MSG_ACCEPTED;
  218. rply.acpted_rply.ar_verf = xprt->xp_verf;
  219. rply.acpted_rply.ar_stat = SUCCESS;
  220. rply.acpted_rply.ar_results.where = xdr_location;
  221. rply.acpted_rply.ar_results.proc = xdr_results;
  222. return (SVC_REPLY(xprt, &rply));
  223. }
  224. /*
  225.  * No procedure error reply
  226.  */
  227. void
  228. svcerr_noproc(xprt)
  229. register SVCXPRT *xprt;
  230. {
  231. struct rpc_msg rply;
  232. rply.rm_direction = REPLY;
  233. rply.rm_reply.rp_stat = MSG_ACCEPTED;
  234. rply.acpted_rply.ar_verf = xprt->xp_verf;
  235. rply.acpted_rply.ar_stat = PROC_UNAVAIL;
  236. SVC_REPLY(xprt, &rply);
  237. }
  238. /*
  239.  * Can't decode args error reply
  240.  */
  241. void
  242. svcerr_decode(xprt)
  243. register SVCXPRT *xprt;
  244. {
  245. struct rpc_msg rply;
  246. rply.rm_direction = REPLY;
  247. rply.rm_reply.rp_stat = MSG_ACCEPTED;
  248. rply.acpted_rply.ar_verf = xprt->xp_verf;
  249. rply.acpted_rply.ar_stat = GARBAGE_ARGS;
  250. SVC_REPLY(xprt, &rply);
  251. }
  252. /*
  253.  * Some system error
  254.  */
  255. void
  256. svcerr_systemerr(xprt)
  257. register SVCXPRT *xprt;
  258. {
  259. struct rpc_msg rply;
  260. rply.rm_direction = REPLY;
  261. rply.rm_reply.rp_stat = MSG_ACCEPTED;
  262. rply.acpted_rply.ar_verf = xprt->xp_verf;
  263. rply.acpted_rply.ar_stat = SYSTEM_ERR;
  264. SVC_REPLY(xprt, &rply);
  265. }
  266. /*
  267.  * Authentication error reply
  268.  */
  269. void
  270. svcerr_auth(xprt, why)
  271. SVCXPRT *xprt;
  272. enum auth_stat why;
  273. {
  274. struct rpc_msg rply;
  275. rply.rm_direction = REPLY;
  276. rply.rm_reply.rp_stat = MSG_DENIED;
  277. rply.rjcted_rply.rj_stat = AUTH_ERROR;
  278. rply.rjcted_rply.rj_why = why;
  279. SVC_REPLY(xprt, &rply);
  280. }
  281. /*
  282.  * Auth too weak error reply
  283.  */
  284. void
  285. svcerr_weakauth(xprt)
  286. SVCXPRT *xprt;
  287. {
  288. svcerr_auth(xprt, AUTH_TOOWEAK);
  289. }
  290. /*
  291.  * Program unavailable error reply
  292.  */
  293. void
  294. svcerr_noprog(xprt)
  295. register SVCXPRT *xprt;
  296. {
  297. struct rpc_msg rply;
  298. rply.rm_direction = REPLY;
  299. rply.rm_reply.rp_stat = MSG_ACCEPTED;
  300. rply.acpted_rply.ar_verf = xprt->xp_verf;
  301. rply.acpted_rply.ar_stat = PROG_UNAVAIL;
  302. SVC_REPLY(xprt, &rply);
  303. }
  304. /*
  305.  * Program version mismatch error reply
  306.  */
  307. void
  308. svcerr_progvers(xprt, low_vers, high_vers)
  309. register SVCXPRT *xprt;
  310. u_long low_vers;
  311. u_long high_vers;
  312. {
  313. struct rpc_msg rply;
  314. rply.rm_direction = REPLY;
  315. rply.rm_reply.rp_stat = MSG_ACCEPTED;
  316. rply.acpted_rply.ar_verf = xprt->xp_verf;
  317. rply.acpted_rply.ar_stat = PROG_MISMATCH;
  318. rply.acpted_rply.ar_vers.low = low_vers;
  319. rply.acpted_rply.ar_vers.high = high_vers;
  320. SVC_REPLY(xprt, &rply);
  321. }
  322. /* ******************* SERVER INPUT STUFF ******************* */
  323. /*
  324.  * Get server side input from some transport.
  325.  *
  326.  * Statement of authentication parameters management:
  327.  * This function owns and manages all authentication parameters, specifically
  328.  * the "raw" parameters (msg.rm_call.cb_cred and msg.rm_call.cb_verf) and
  329.  * the "cooked" credentials (rqst->rq_clntcred).  However, this function
  330.  * does not know the structure of the cooked credentials, so it make the
  331.  * following two assumptions: a) the structure is contiguous (no pointers), and
  332.  * b) the structure size does not exceed RQCRED_SIZE bytes.
  333.  * In all events, all three parameters are freed upon exit from this routine.
  334.  * The storage is trivially management on the call stack in user land, but
  335.  * is mallocated in kernel land.
  336.  */
  337. void
  338. svc_getreq (rdfds)
  339.     int rdfds;
  340.     {
  341.     fd_set readFds; /* 4.0 */
  342.     FD_ZERO (&readFds); /* 4.0 */
  343.     readFds.fds_bits[0] = rdfds; /* 4.0 */
  344.     svc_getreqset (&readFds); /* 4.0 */
  345.     }
  346. void
  347. svc_getreqset (rdfds)
  348. fd_set *rdfds;
  349. {
  350. register enum xprt_stat stat;
  351. struct rpc_msg msg;
  352. int prog_found;
  353. u_long low_vers;
  354. u_long high_vers;
  355. struct svc_req r;
  356. register int sock;
  357. register SVCXPRT *xprt;
  358. /* XXX char cred_area[2*MAX_AUTH_BYTES + RQCRED_SIZE]; */
  359. char *cred_area = (char *) KHEAP_ALLOC(2*MAX_AUTH_BYTES + RQCRED_SIZE);
  360. FAST struct svc *ms = &taskRpcStatics->svc;
  361. fd_set readFds;
  362. if (cred_area == 0) /* 4.0 */
  363.     { /* 4.0 */
  364.     panic ("rpc: svc_getreq: out of memory.n"); /* 4.0 */
  365.     return; /* 4.0 */
  366.     } /* 4.0 */
  367. msg.rm_call.cb_cred.oa_base = cred_area; /* 4.0 */
  368. msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]); /* 4.0 */
  369. r.rq_clntcred = &(cred_area[2*MAX_AUTH_BYTES]); /* 4.0 */
  370. /*
  371.  * The following is the code that gets a list of socket ports
  372.  * that are ready for input.  In comments is the RPC 4.0 optimized
  373.  * version that makes use of getdtablesize() and ffs() which VxWorks
  374.  * doesn't have yet.  So we use the 3.9 unoptimized version instead.
  375.  * The code here replaces the code between MARK-A and MARK-B.
  376.  *
  377.  * setsize = _rpc_dtablesize();  // or just call getdtablesize ()
  378.  * maskp = (u_long *) readFds->fds_bits;
  379.  * for (sock = 0; sock < setsize; sock += NFDBITS)
  380.  *    {
  381.  *    for (mask = *maskp++; bit = ffs (mask); mask ^= (1 << (bit - 1)))
  382.  *        {
  383.  *        // sock has input waiting
  384.  *        xprt = xports [sock + bit - 1];
  385.  */
  386. /* MARK-A     see the comment above */
  387. FD_ZERO(&readFds);
  388. for (sock = 0; sock < FD_SETSIZE; sock++)
  389.     if (FD_ISSET(sock, &ms->svc_fdset) && FD_ISSET(sock, rdfds))
  390. FD_SET(sock, &readFds);
  391. for (sock = 0; sock < FD_SETSIZE; sock++) {
  392.     if (FD_ISSET(sock, &readFds)) {
  393. /* sock has input waiting */
  394. xprt = ms->xports[sock];
  395. /* MARK-B     see the comment above */
  396. /* now receive msgs from xprtprt (support batch calls) */
  397. do {
  398. if (SVC_RECV(xprt, &msg)) {
  399. /* now find the exported program and call it */
  400. register struct svc_callout *s;
  401. enum auth_stat why;
  402. r.rq_xprt = xprt;
  403. r.rq_prog = msg.rm_call.cb_prog;
  404. r.rq_vers = msg.rm_call.cb_vers;
  405. r.rq_proc = msg.rm_call.cb_proc;
  406. r.rq_cred = msg.rm_call.cb_cred;
  407. /* first authenticate the message */
  408. if ((why= _authenticate(&r, &msg)) != AUTH_OK) {
  409. svcerr_auth(xprt, why);
  410. goto call_done;
  411. }
  412. /* now match message with a registered service*/
  413. prog_found = FALSE;
  414. low_vers = 0 - 1;
  415. high_vers = 0;
  416. for (s = ms->svc_head; s != NULL_SVC; s = s->sc_next) {
  417. if (s->sc_prog == r.rq_prog) {
  418. if (s->sc_vers == r.rq_vers) {
  419. (*s->sc_dispatch)(&r, xprt);
  420. goto call_done;
  421. }  /* found correct version */
  422. prog_found = TRUE;
  423. if (s->sc_vers < low_vers)
  424. low_vers = s->sc_vers;
  425. if (s->sc_vers > high_vers)
  426. high_vers = s->sc_vers;
  427. }   /* found correct program */
  428. }
  429. /*
  430.  * if we got here, the program or version
  431.  * is not served ...
  432.  */
  433. if (prog_found)
  434. svcerr_progvers(xprt,
  435. low_vers, high_vers);
  436. else
  437.  svcerr_noprog(xprt);
  438. /* Fall through to ... */
  439. }
  440. call_done:
  441. if ((stat = SVC_STAT(xprt)) == XPRT_DIED){
  442. SVC_DESTROY(xprt);
  443. break;
  444. }
  445. } while (stat == XPRT_MOREREQS);
  446.     }
  447. }
  448.     KHEAP_FREE(cred_area);
  449. }
  450. /*
  451.  * This is the rpc server side idle loop
  452.  * Wait for input, call server program.
  453.  */
  454. void
  455. svc_run()
  456. {
  457. fd_set readFds;
  458. FAST struct svc *ms = &taskRpcStatics->svc;
  459. while (TRUE) {
  460. readFds = ms->svc_fdset;
  461. switch (select (FD_SETSIZE, &readFds, (fd_set *)NULL,
  462. (fd_set *)NULL, (struct timeval *)0))
  463. {
  464. case -1:
  465. if (rpcErrnoGet () == EINTR)
  466. continue;
  467. else {
  468. perror("svc.c: - Select failed");
  469. return;
  470. }
  471. case 0:
  472. continue;
  473. default:
  474. svc_getreqset (&readFds);
  475. }
  476. }
  477. }