home *** CD-ROM | disk | FTP | other *** search
/ Serving the Web / ServingTheWeb1995.disc1of1.iso / linux / slacksrce / d / libc / libc-4.6 / libc-4 / libc-linux / rpc / svc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-29  |  11.3 KB  |  490 lines

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