home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume6 / rpc2 / part07 / rpc / rpclib / svc.c < prev   
Encoding:
C/C++ Source or Header  |  1986-11-30  |  10.4 KB  |  457 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.  
  43. #include "types.h"
  44. #include <sys/errno.h>
  45. #include <sys/time.h>
  46. #include <netinet/in.h>
  47. #include "xdr.h"
  48. #include "auth.h"
  49. #include "clnt.h"
  50. #include "rpc_msg.h"
  51. #include "svc.h"
  52. #include "svc_auth.h"
  53. #include "pmap_clnt.h"
  54.  
  55. #define NOFILE 32
  56.  
  57. static SVCXPRT *xports[NOFILE];
  58. int svc_fds;
  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 &= ~(1 << 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.     if (protocol) {
  146.         return (pmap_set(prog, vers, protocol, xprt->xp_port));
  147.     }
  148.     return (TRUE);
  149. }
  150.  
  151. /*
  152.  * Remove a service program from the callout list.
  153.  */
  154. void
  155. svc_unregister(prog, vers)
  156.     u_long prog;
  157.     u_long vers;
  158. {
  159.     struct svc_callout *prev;
  160.     register struct svc_callout *s;
  161.  
  162.     if ((s = svc_find(prog, vers, &prev)) == NULL_SVC)
  163.         return;
  164.     if (prev == NULL_SVC) {
  165.         svc_head = s->sc_next;
  166.     } else {
  167.         prev->sc_next = s->sc_next;
  168.     }
  169.     s->sc_next = NULL_SVC;
  170.     mem_free((char *) s, (u_int) sizeof(struct svc_callout));
  171.     /* now unregister the information with the local binder service */
  172.     (void)pmap_unset(prog, vers);
  173. }
  174.  
  175. /*
  176.  * Search the callout list for a program number, return the callout
  177.  * struct.
  178.  */
  179. static struct svc_callout *
  180. svc_find(prog, vers, prev)
  181.     u_long prog;
  182.     u_long vers;
  183.     struct svc_callout **prev;
  184. {
  185.     register struct svc_callout *s, *p;
  186.  
  187.     p = NULL_SVC;
  188.     for (s = svc_head; s != NULL_SVC; s = s->sc_next) {
  189.         if ((s->sc_prog == prog) && (s->sc_vers == vers))
  190.             goto done;
  191.         p = s;
  192.     }
  193. done:
  194.     *prev = p;
  195.     return (s);
  196. }
  197.  
  198. /* ******************* REPLY GENERATION ROUTINES  ************ */
  199.  
  200. /*
  201.  * Send a reply to an rpc request
  202.  */
  203. bool_t
  204. svc_sendreply(xprt, xdr_results, xdr_location)
  205.     register SVCXPRT *xprt;
  206.     xdrproc_t xdr_results;
  207.     caddr_t xdr_location;
  208. {
  209.     struct rpc_msg rply; 
  210.  
  211.     rply.rm_direction = REPLY;  
  212.     rply.rm_reply.rp_stat = MSG_ACCEPTED; 
  213.     rply.acpted_rply.ar_verf = xprt->xp_verf; 
  214.     rply.acpted_rply.ar_stat = SUCCESS;
  215.     rply.acpted_rply.ar_results.where = xdr_location;
  216.     rply.acpted_rply.ar_results.proc = xdr_results;
  217.     return (SVC_REPLY(xprt, &rply)); 
  218. }
  219.  
  220. /*
  221.  * No procedure error reply
  222.  */
  223. void
  224. svcerr_noproc(xprt)
  225.     register SVCXPRT *xprt;
  226. {
  227.     struct rpc_msg rply;
  228.  
  229.     rply.rm_direction = REPLY;
  230.     rply.rm_reply.rp_stat = MSG_ACCEPTED;
  231.     rply.acpted_rply.ar_verf = xprt->xp_verf;
  232.     rply.acpted_rply.ar_stat = PROC_UNAVAIL;
  233.     SVC_REPLY(xprt, &rply);
  234. }
  235.  
  236. /*
  237.  * Can't decode args error reply
  238.  */
  239. void
  240. svcerr_decode(xprt)
  241.     register SVCXPRT *xprt;
  242. {
  243.     struct rpc_msg rply; 
  244.  
  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 = GARBAGE_ARGS;
  249.     SVC_REPLY(xprt, &rply); 
  250. }
  251.  
  252. /*
  253.  * Some system error
  254.  */
  255. void
  256. svcerr_systemerr(xprt)
  257.     register SVCXPRT *xprt;
  258. {
  259.     struct rpc_msg rply; 
  260.  
  261.     rply.rm_direction = REPLY; 
  262.     rply.rm_reply.rp_stat = MSG_ACCEPTED; 
  263.     rply.acpted_rply.ar_verf = xprt->xp_verf;
  264.     rply.acpted_rply.ar_stat = SYSTEM_ERR;
  265.     SVC_REPLY(xprt, &rply); 
  266. }
  267.  
  268. /*
  269.  * Authentication error reply
  270.  */
  271. void
  272. svcerr_auth(xprt, why)
  273.     SVCXPRT *xprt;
  274.     enum auth_stat why;
  275. {
  276.     struct rpc_msg rply;
  277.  
  278.     rply.rm_direction = REPLY;
  279.     rply.rm_reply.rp_stat = MSG_DENIED;
  280.     rply.rjcted_rply.rj_stat = AUTH_ERROR;
  281.     rply.rjcted_rply.rj_why = why;
  282.     SVC_REPLY(xprt, &rply);
  283. }
  284.  
  285. /*
  286.  * Auth too weak error reply
  287.  */
  288. void
  289. svcerr_weakauth(xprt)
  290.     SVCXPRT *xprt;
  291. {
  292.  
  293.     svcerr_auth(xprt, AUTH_TOOWEAK);
  294. }
  295.  
  296. /*
  297.  * Program unavailable error reply
  298.  */
  299. void 
  300. svcerr_noprog(xprt)
  301.     register SVCXPRT *xprt;
  302. {
  303.     struct rpc_msg rply;  
  304.  
  305.     rply.rm_direction = REPLY;   
  306.     rply.rm_reply.rp_stat = MSG_ACCEPTED;  
  307.     rply.acpted_rply.ar_verf = xprt->xp_verf;  
  308.     rply.acpted_rply.ar_stat = PROG_UNAVAIL;
  309.     SVC_REPLY(xprt, &rply);
  310. }
  311.  
  312. /*
  313.  * Program version mismatch error reply
  314.  */
  315. void  
  316. svcerr_progvers(xprt, low_vers, high_vers)
  317.     register SVCXPRT *xprt; 
  318.     u_long low_vers;
  319.     u_long high_vers;
  320. {
  321.     struct rpc_msg rply;
  322.  
  323.     rply.rm_direction = REPLY;
  324.     rply.rm_reply.rp_stat = MSG_ACCEPTED;
  325.     rply.acpted_rply.ar_verf = xprt->xp_verf;
  326.     rply.acpted_rply.ar_stat = PROG_MISMATCH;
  327.     rply.acpted_rply.ar_vers.low = low_vers;
  328.     rply.acpted_rply.ar_vers.high = high_vers;
  329.     SVC_REPLY(xprt, &rply);
  330. }
  331.  
  332. /* ******************* SERVER INPUT STUFF ******************* */
  333.  
  334. /*
  335.  * Get server side input from some transport.
  336.  *
  337.  * Statement of authentication parameters management:
  338.  * This function owns and manages all authentication parameters, specifically
  339.  * the "raw" parameters (msg.rm_call.cb_cred and msg.rm_call.cb_verf) and
  340.  * the "cooked" credentials (rqst->rq_clntcred).  However, this function
  341.  * does not know the structure of the cooked credentials, so it make the
  342.  * following two assumptions: a) the structure is contiguous (no pointers), and
  343.  * b) the structure size does not exceed RQCRED_SIZE bytes. 
  344.  * In all events, all three parameters are freed upon exit from this routine.
  345.  * The storage is trivially management on the call stack in user land, but
  346.  * is mallocated in kernel land.
  347.  */
  348. void
  349. svc_getreq(rdfds)
  350.     int rdfds;
  351. {
  352.     register enum xprt_stat stat;
  353.     struct rpc_msg msg;
  354.     int prog_found;
  355.     u_long low_vers;
  356.     u_long high_vers;
  357.     struct svc_req r;
  358.     register int sock;
  359.     register int readfds = rdfds & svc_fds;
  360.     register SVCXPRT *xprt;
  361.     char cred_area[2*MAX_AUTH_BYTES + RQCRED_SIZE];
  362.     msg.rm_call.cb_cred.oa_base = cred_area;
  363.     msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]);
  364.     r.rq_clntcred = &(cred_area[2*MAX_AUTH_BYTES]);
  365.  
  366.     for (sock = 0; readfds != 0; sock++, readfds >>= 1) {
  367.         if ((readfds & 1) != 0) {
  368.         /* sock has input waiting */
  369.         xprt = xports[sock];
  370.         /* now receive msgs from xprtprt (support batch calls) */
  371.         do {
  372.             if (SVC_RECV(xprt, &msg)) {
  373.  
  374.                 /* now find the exported program and call it */
  375.                 register struct svc_callout *s;
  376.                 enum auth_stat why;
  377.  
  378.                 r.rq_xprt = xprt;
  379.                 r.rq_prog = msg.rm_call.cb_prog;
  380.                 r.rq_vers = msg.rm_call.cb_vers;
  381.                 r.rq_proc = msg.rm_call.cb_proc;
  382.                 r.rq_cred = msg.rm_call.cb_cred;
  383.                 /* first authenticate the message */
  384.                 if ((why= _authenticate(&r, &msg)) != AUTH_OK) {
  385.                     svcerr_auth(xprt, why);
  386.                     goto call_done;
  387.                 }
  388.                 /* now match message with a registered service*/
  389.                 prog_found = FALSE;
  390.                 low_vers = 0 - 1;
  391.                 high_vers = 0;
  392.                 for (s = svc_head; s != NULL_SVC; s = s->sc_next) {
  393.                     if (s->sc_prog == r.rq_prog) {
  394.                         if (s->sc_vers == r.rq_vers) {
  395.                             (*s->sc_dispatch)(&r, xprt);
  396.                             goto call_done;
  397.                         }  /* found correct version */
  398.                         prog_found = TRUE;
  399.                         if (s->sc_vers < low_vers)
  400.                             low_vers = s->sc_vers;
  401.                         if (s->sc_vers > high_vers)
  402.                             high_vers = s->sc_vers;
  403.                     }   /* found correct program */
  404.                 }
  405.                 /*
  406.                  * if we got here, the program or version
  407.                  * is not served ...
  408.                  */
  409.                 if (prog_found)
  410.                     svcerr_progvers(xprt,
  411.                     low_vers, high_vers);
  412.                 else
  413.                      svcerr_noprog(xprt);
  414.                 /* Fall through to ... */
  415.             }
  416.         call_done:
  417.             if ((stat = SVC_STAT(xprt)) == XPRT_DIED){
  418.                 SVC_DESTROY(xprt);
  419.                 break;
  420.             }
  421.         } while (stat == XPRT_MOREREQS);
  422.         }
  423.     }
  424. }
  425.  
  426.  
  427. /*
  428.  * This is the rpc server side idle loop
  429.  * Wait for input, call server program.
  430.  */
  431. void
  432. svc_run()
  433. {
  434.     int readfds;
  435.  
  436.     while (TRUE) {
  437.         readfds = svc_fds;
  438.         switch (select(32, &readfds, (int *)0, (int *)0,
  439.             (struct timeval *)0)) {
  440.  
  441.         case -1:
  442.             if (errno == EINTR)
  443.                 continue;
  444.             else {
  445.                 perror("svc.c: - Select failed");
  446.                 return;
  447.             }
  448.         case 0:
  449.             continue;
  450.         default:
  451.             svc_getreq(readfds);
  452.         }
  453.     }
  454. }
  455.