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