home *** CD-ROM | disk | FTP | other *** search
/ Black Box 4 / BlackBox.cdr / lan / soss.arj / RPC / SVC.C < prev    next >
C/C++ Source or Header  |  1991-02-22  |  11KB  |  464 lines

  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. #ifndef lint
  30. static char sccsid[] = "@(#)svc.c 1.1 86/02/03 Copyr 1984 Sun Micro";
  31. #endif
  32.  
  33. /*
  34.  * svc.c, Server-side remote procedure call interface.
  35.  *
  36.  * There are two sets of procedures here.  The xprt routines are
  37.  * for handling transport handles.  The svc routines handle the
  38.  * list of service routines.
  39.  *
  40.  * Copyright (C) 1984, Sun Microsystems, Inc.
  41.  */
  42. #include "sock.h"
  43. #include "types.h"
  44. #include <errno.h>
  45. #include "in.h"
  46. #include "xdr.h"
  47. #include "auth.h"
  48. #include "clnt.h"
  49. #include "rpc_msg.h"
  50. #include "svc.h"
  51. #include "svc_auth.h"
  52. #include "p_clnt.h"
  53. #include <conio.h>
  54.  
  55. #define NOFILE 32
  56.  
  57. static SVCXPRT *xports[NOFILE];
  58. long svc_fds = 0;
  59. extern errno;
  60. char *malloc();
  61.  
  62. #define NULL_SVC ((struct svc_callout *)0)
  63. #define    RQCRED_SIZE    400
  64.  
  65. /*
  66.  * The services list
  67.  * Each entry represents a set of procedures (an rpc program).
  68.  * The dispatch routine takes request structs and runs the
  69.  * apropriate procedure.
  70.  */
  71. static struct svc_callout {
  72.     struct svc_callout *sc_next;
  73.     u_long            sc_prog;
  74.     u_long            sc_vers;
  75.     void            (*sc_dispatch)();
  76. } *svc_head;
  77.  
  78. static struct svc_callout *svc_find();
  79.  
  80. /* ***************  SVCXPRT related stuff **************** */
  81.  
  82. /*
  83.  * Activate a transport handle.
  84.  */
  85. void
  86. xprt_register(xprt)
  87.     SVCXPRT *xprt;
  88. {
  89.     register int sock = xprt->xp_sock;
  90.  
  91.     if (sock < NOFILE) {
  92.         xports[sock] = xprt;
  93.         svc_fds |= (1 << sock);
  94.     }
  95. }
  96.  
  97. /*
  98.  * De-activate a transport handle. 
  99.  */
  100. void
  101. xprt_unregister(xprt) 
  102.     SVCXPRT *xprt;
  103.     register int sock = xprt->xp_sock;
  104.  
  105.     if ((sock < NOFILE) && (xports[sock] == xprt)) {
  106.         xports[sock] = (SVCXPRT *)0;
  107.         svc_fds &= ~(1L << sock);
  108.     }
  109.  
  110.  
  111. /* ********************** CALLOUT list related stuff ************* */
  112.  
  113. /*
  114.  * Add a service program to the callout list.
  115.  * The dispatch routine will be called when a rpc request for this
  116.  * program number comes in.
  117.  */
  118. bool_t
  119. svc_register(xprt, prog, vers, dispatch, protocol)
  120.     SVCXPRT *xprt;
  121.     u_long prog;
  122.     u_long vers;
  123.     void (*dispatch)();
  124.     int protocol;
  125. {
  126.     struct svc_callout *prev;
  127.     register struct svc_callout *s;
  128.  
  129.     if ((s = svc_find(prog, vers, &prev)) != NULL_SVC) {
  130.         if (s->sc_dispatch == dispatch)
  131.             goto pmap_it;  /* he is registering another xptr */
  132.         return (FALSE);
  133.     }
  134.     s = (struct svc_callout *)mem_alloc(sizeof(struct svc_callout));
  135.     if (s == (struct svc_callout *)0) {
  136.         return (FALSE);
  137.     }
  138.     s->sc_prog = prog;
  139.     s->sc_vers = vers;
  140.     s->sc_dispatch = dispatch;
  141.     s->sc_next = svc_head;
  142.     svc_head = s;
  143. pmap_it:
  144.     /* now register the information with the local binder service */
  145.     /* port map service not available on the PC */
  146.         /* See-Mong Tan, 6/14/88 */
  147. /*    if (protocol) {
  148.         return (pmap_set(prog, vers, protocol, xprt->xp_port));
  149.     }
  150. */
  151.     return (TRUE);
  152. }
  153.  
  154. /*
  155.  * Remove a service program from the callout list.
  156.  */
  157. void
  158. svc_unregister(prog, vers)
  159.     u_long prog;
  160.     u_long vers;
  161. {
  162.     struct svc_callout *prev;
  163.     register struct svc_callout *s;
  164.  
  165.     if ((s = svc_find(prog, vers, &prev)) == NULL_SVC)
  166.         return;
  167.     if (prev == NULL_SVC) {
  168.         svc_head = s->sc_next;
  169.     } else {
  170.         prev->sc_next = s->sc_next;
  171.     }
  172.     s->sc_next = NULL_SVC;
  173.     mem_free((char *) s, (u_int) sizeof(struct svc_callout));
  174.     /* now unregister the information with the local binder service */
  175. /*    (void)pmap_unset(prog, vers);    */
  176. }
  177.  
  178. /*
  179.  * Search the callout list for a program number, return the callout
  180.  * struct.
  181.  */
  182. static struct svc_callout *
  183. svc_find(prog, vers, prev)
  184.     u_long prog;
  185.     u_long vers;
  186.     struct svc_callout **prev;
  187. {
  188.     register struct svc_callout *s, *p;
  189.  
  190.     p = NULL_SVC;
  191.     for (s = svc_head; s != NULL_SVC; s = s->sc_next) {
  192.         if ((s->sc_prog == prog) && (s->sc_vers == vers))
  193.             goto done;
  194.         p = s;
  195.     }
  196. done:
  197.     *prev = p;
  198.     return (s);
  199. }
  200.  
  201. /* ******************* REPLY GENERATION ROUTINES  ************ */
  202.  
  203. /*
  204.  * Send a reply to an rpc request
  205.  */
  206. bool_t
  207. svc_sendreply(xprt, xdr_results, xdr_location)
  208.     register SVCXPRT *xprt;
  209.     xdrproc_t xdr_results;
  210.     caddr_t xdr_location;
  211. {
  212.     struct rpc_msg rply; 
  213.  
  214.     rply.rm_direction = REPLY;  
  215.     rply.rm_reply.rp_stat = MSG_ACCEPTED; 
  216.     rply.acpted_rply.ar_verf = xprt->xp_verf; 
  217.     rply.acpted_rply.ar_stat = SUCCESS1;
  218.     rply.acpted_rply.ar_results.where = xdr_location;
  219.     rply.acpted_rply.ar_results.proc = xdr_results;
  220.     return (SVC_REPLY(xprt, &rply)); 
  221. }
  222.  
  223. /*
  224.  * No procedure error reply
  225.  */
  226. void
  227. svcerr_noproc(xprt)
  228.     register SVCXPRT *xprt;
  229. {
  230.     struct rpc_msg rply;
  231.  
  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. /*
  240.  * Can't decode args error reply
  241.  */
  242. void
  243. svcerr_decode(xprt)
  244.     register SVCXPRT *xprt;
  245. {
  246.     struct rpc_msg rply; 
  247.  
  248.     rply.rm_direction = REPLY; 
  249.     rply.rm_reply.rp_stat = MSG_ACCEPTED; 
  250.     rply.acpted_rply.ar_verf = xprt->xp_verf;
  251.     rply.acpted_rply.ar_stat = GARBAGE_ARGS;
  252.     SVC_REPLY(xprt, &rply); 
  253. }
  254.  
  255. /*
  256.  * Some system error
  257.  */
  258. void
  259. svcerr_systemerr(xprt)
  260.     register SVCXPRT *xprt;
  261. {
  262.     struct rpc_msg rply; 
  263.  
  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 = SYSTEM_ERR;
  268.     SVC_REPLY(xprt, &rply); 
  269. }
  270.  
  271. /*
  272.  * Authentication error reply
  273.  */
  274. void
  275. svcerr_auth(xprt, why)
  276.     SVCXPRT *xprt;
  277.     enum auth_stat why;
  278. {
  279.     struct rpc_msg rply;
  280.  
  281.     rply.rm_direction = REPLY;
  282.     rply.rm_reply.rp_stat = MSG_DENIED;
  283.     rply.rjcted_rply.rj_stat = AUTH_ERROR;
  284.     rply.rjcted_rply.rj_why = why;
  285.     SVC_REPLY(xprt, &rply);
  286. }
  287.  
  288. /*
  289.  * Auth too weak error reply
  290.  */
  291. void
  292. svcerr_weakauth(xprt)
  293.     SVCXPRT *xprt;
  294. {
  295.  
  296.     svcerr_auth(xprt, AUTH_TOOWEAK);
  297. }
  298.  
  299. /*
  300.  * Program unavailable error reply
  301.  */
  302. void 
  303. svcerr_noprog(xprt)
  304.     register SVCXPRT *xprt;
  305. {
  306.     struct rpc_msg rply;  
  307.  
  308.     rply.rm_direction = REPLY;   
  309.     rply.rm_reply.rp_stat = MSG_ACCEPTED;  
  310.     rply.acpted_rply.ar_verf = xprt->xp_verf;  
  311.     rply.acpted_rply.ar_stat = PROG_UNAVAIL;
  312.     SVC_REPLY(xprt, &rply);
  313. }
  314.  
  315. /*
  316.  * Program version mismatch error reply
  317.  */
  318. void  
  319. svcerr_progvers(xprt, low_vers, high_vers)
  320.     register SVCXPRT *xprt; 
  321.     u_long low_vers;
  322.     u_long high_vers;
  323. {
  324.     struct rpc_msg rply;
  325.  
  326.     rply.rm_direction = REPLY;
  327.     rply.rm_reply.rp_stat = MSG_ACCEPTED;
  328.     rply.acpted_rply.ar_verf = xprt->xp_verf;
  329.     rply.acpted_rply.ar_stat = PROG_MISMATCH;
  330.     rply.acpted_rply.ar_vers.low = low_vers;
  331.     rply.acpted_rply.ar_vers.high = high_vers;
  332.     SVC_REPLY(xprt, &rply);
  333. }
  334.  
  335. /* ******************* SERVER INPUT STUFF ******************* */
  336.  
  337. /*
  338.  * Get server side input from some transport.
  339.  *
  340.  * Statement of authentication parameters management:
  341.  * This function owns and manages all authentication parameters, specifically
  342.  * the "raw" parameters (msg.rm_call.cb_cred and msg.rm_call.cb_verf) and
  343.  * the "cooked" credentials (rqst->rq_clntcred).  However, this function
  344.  * does not know the structure of the cooked credentials, so it make the
  345.  * following two assumptions: a) the structure is contiguous (no pointers), and
  346.  * b) the structure size does not exceed RQCRED_SIZE bytes. 
  347.  * In all events, all three parameters are freed upon exit from this routine.
  348.  * The storage is trivially management on the call stack in user land, but
  349.  * is mallocated in kernel land.
  350.  */
  351. void
  352. svc_getreq(rdfds)
  353.     long rdfds;
  354. {
  355.     register enum xprt_stat stat;
  356.     struct rpc_msg msg;
  357.     int prog_found;
  358.     u_long low_vers;
  359.     u_long high_vers;
  360.     struct svc_req r;
  361.     register int sock;
  362.     long int readfds = rdfds & svc_fds;
  363.     register SVCXPRT *xprt;
  364.     char cred_area[2*MAX_AUTH_BYTES + RQCRED_SIZE];
  365.     msg.rm_call.cb_cred.oa_base = cred_area;
  366.     msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]);
  367.     r.rq_clntcred = &(cred_area[2*MAX_AUTH_BYTES]);
  368.  
  369.     for (sock = 0; readfds != 0; sock++, readfds >>= 1L) {
  370.         if ((readfds & 1L) != 0) {
  371.         /* sock has input waiting */
  372.         xprt = xports[sock];
  373.         /* now receive msgs from xprt (support batch calls) */
  374.         do {
  375.             if (SVC_RECV(xprt, &msg)) {
  376.                 /* now find the exported program and call it */
  377.                 register struct svc_callout *s;
  378.                 enum auth_stat why;
  379.  
  380.                 r.rq_xprt = xprt;
  381.                 r.rq_prog = msg.rm_call.cb_prog;
  382.                 r.rq_vers = msg.rm_call.cb_vers;
  383.                 r.rq_proc = msg.rm_call.cb_proc;
  384.                 r.rq_cred = msg.rm_call.cb_cred;
  385.                 /* first authenticate the message */
  386.                 if ((why= _authenticate(&r, &msg)) != AUTH_OK) {
  387.                     svcerr_auth(xprt, why);
  388.                     goto call_done;
  389.                 }
  390.                 /* now match message with a registered service*/
  391.                 prog_found = FALSE;
  392.                 low_vers = 0 - 1;
  393.                 high_vers = 0;
  394.                 for (s = svc_head; s != NULL_SVC; s = s->sc_next) {
  395.                     if (s->sc_prog == r.rq_prog) {
  396.                         if (s->sc_vers == r.rq_vers) {
  397.                             (*s->sc_dispatch)(&r, xprt);
  398.                             goto call_done;
  399.                         }  /* found correct version */
  400.                         prog_found = TRUE;
  401.                         if (s->sc_vers < low_vers)
  402.                             low_vers = s->sc_vers;
  403.                         if (s->sc_vers > high_vers)
  404.                             high_vers = s->sc_vers;
  405.                     }   /* found correct program */
  406.                 }
  407.                 /*
  408.                  * if we got here, the program or version
  409.                  * is not served ...
  410.                  */
  411.                 if (prog_found)
  412.                     svcerr_progvers(xprt,
  413.                     low_vers, high_vers);
  414.                 else
  415.                      svcerr_noprog(xprt);
  416.                 /* Fall through to ... */
  417.             }
  418.         call_done:
  419.             if ((stat = SVC_STAT(xprt)) == XPRT_DIED){
  420.                 SVC_DESTROY(xprt);
  421.                 break;
  422.             }
  423.         } while (stat == XPRT_MOREREQS);
  424.         }
  425.     }
  426. }
  427.  
  428.  
  429. /*
  430.  * This is the rpc server side idle loop
  431.  * Wait for input, call server program.
  432.  */
  433. void
  434. svc_run()
  435. {
  436.     long readfds;
  437.  
  438.     while (TRUE) {
  439.         if(kbhit()) {
  440.             if(getch() == 'q') {
  441.             printf("\nTermination requested.\n");
  442.             exit(0);
  443.             }
  444.         }
  445.         readfds = svc_fds;
  446.         switch (sock_select(&readfds, (long *)0)) {
  447.  
  448.         case -1:
  449.             if (errno == EINTR || errno == EWOULDBLOCK)
  450.                 continue;
  451.             else {
  452.                 perror("svc.c: - Select failed");
  453.                 return;
  454.             }
  455.         case 0:
  456.             continue;
  457.         default:
  458.             svc_getreq(readfds);
  459.         }
  460.     }
  461. }
  462.