home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume1 / rpc / part09 < prev    next >
Encoding:
Internet Message Format  |  1986-11-30  |  55.2 KB

  1. Date: Wed, 3 Apr 85 00:16:07 pst
  2. From: decvax!sun!pumpkinseed!blyon (Bob Lyon)
  3. Subject: Sun RPC part 9 of 10
  4.  
  5. echo x - svc.c
  6. sed 's/^X//' >svc.c <<'!Funky!Stuff!'
  7. /*
  8.  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  9.  * unrestricted use provided that this legend is included on all tape
  10.  * media and as a part of the software program in whole or part.  Users
  11.  * may copy or modify Sun RPC without charge, but are not authorized
  12.  * to license or distribute it to anyone else except as part of a product or
  13.  * program developed by the user.
  14.  * 
  15.  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  16.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  17.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  18.  * 
  19.  * Sun RPC is provided with no support and without any obligation on the
  20.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  21.  * modification or enhancement.
  22.  * 
  23.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  24.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  25.  * OR ANY PART THEREOF.
  26.  * 
  27.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  28.  * or profits or other special, indirect and consequential damages, even if
  29.  * Sun has been advised of the possibility of such damages.
  30.  * 
  31.  * Sun Microsystems, Inc.
  32.  * 2550 Garcia Avenue
  33.  * Mountain View, California  94043
  34.  */
  35. #ifndef lint
  36. static char sccsid[] = "@(#)svc.c 1.7 85/03/20 Copyr 1984 Sun Micro";
  37. #endif
  38.  
  39. /*
  40.  * svc.c, Server-side remote procedure call interface.
  41.  *
  42.  * There are two sets of procedures here.  The xprt routines are
  43.  * for handling transport handles.  The svc routines handle the
  44.  * list of service routines.
  45.  *
  46.  * Copyright (C) 1984, Sun Microsystems, Inc.
  47.  */
  48.  
  49. #include <stdio.h>
  50. #include "types.h"
  51. #include <sys/errno.h>
  52. #include <netinet/in.h>
  53. #include "xdr.h"
  54. #include "auth.h"
  55. #include "clnt.h"
  56. #include "rpc_msg.h"
  57. #include "svc.h"
  58. #include "svc_auth.h"
  59. #include "pmap_clnt.h"    /* <make kernel depend happy> */
  60.  
  61. #define NOFILE 32
  62.  
  63. static SVCXPRT *xports[NOFILE];
  64. int svc_fds = 0;
  65. extern errno;
  66. char *malloc();
  67.  
  68. #define NULL_SVC ((struct svc_callout *)0)
  69.  
  70. void rpctest_service();
  71.  
  72. /*
  73.  * The services list
  74.  * Each entry represents a set of procedures (an rpc program).
  75.  * The dispatch routine takes request structs and runs the
  76.  * apropriate procedure.
  77.  */
  78. static struct svc_callout {
  79.     struct svc_callout *sc_next;
  80.     u_long            sc_prog;
  81.     u_long            sc_vers;
  82.     void            (*sc_dispatch)();
  83. } *svc_head = NULL_SVC;
  84.  
  85. static struct svc_callout *svc_find();
  86.  
  87. /* ***************  SVCXPRT related stuff **************** */
  88.  
  89. /*
  90.  * Activate a transport handle.
  91.  */
  92. void
  93. xprt_register(xprt)
  94.     SVCXPRT *xprt;
  95. {
  96.     register int sock = xprt->xp_sock;
  97.  
  98.     if (sock < NOFILE) {
  99.         xports[sock] = xprt;
  100.         svc_fds |= (1 << sock);
  101.     }
  102. }
  103.  
  104. /*
  105.  * De-activate a transport handle. 
  106.  */
  107. void
  108. xprt_unregister(xprt) 
  109.     SVCXPRT *xprt;
  110.     register int sock = xprt->xp_sock;
  111.  
  112.     if ((sock < NOFILE) && (xports[sock] == xprt)) {
  113.         xports[sock] = (SVCXPRT *)NULL;
  114.         svc_fds &= ~(1 << sock);
  115.     }
  116.  
  117.  
  118. /* ********************** CALLOUT list related stuff ************* */
  119.  
  120. /*
  121.  * Add a service program to the callout list.
  122.  * The dispatch routine will be called when a rpc request for this
  123.  * program number comes in.
  124.  */
  125. bool_t
  126. svc_register(xprt, prog, vers, dispatch, protocol)
  127.     SVCXPRT *xprt;
  128.     u_long prog;
  129.     u_long vers;
  130.     void (*dispatch)();
  131.     int protocol;
  132. {
  133.     struct svc_callout *prev;
  134.     register struct svc_callout *s;
  135.  
  136.     if ((s = svc_find(prog, vers, &prev)) != NULL_SVC) {
  137.         if (s->sc_dispatch == dispatch)
  138.             goto pmap_it;  /* he is registering another xptr */
  139.         return (FALSE);
  140.     }
  141.     s = (struct svc_callout *)mem_alloc(sizeof(struct svc_callout));
  142.     if (s == NULL) {
  143.         fprintf(stderr, "svc_register: out of memory\n");
  144.         return (FALSE);
  145.     }
  146.     s->sc_prog = prog;
  147.     s->sc_vers = vers;
  148.     s->sc_dispatch = dispatch;
  149.     s->sc_next = svc_head;
  150.     svc_head = s;
  151. pmap_it:
  152.     /* now register the information with the local binder service */
  153.     if (protocol) {
  154.         return (pmap_set(prog, vers, protocol, xprt->xp_port));
  155.     }
  156.     return (TRUE);
  157. }
  158.  
  159. /*
  160.  * Remove a service program from the callout list.
  161.  */
  162. void
  163. svc_unregister(prog, vers)
  164.     u_long prog;
  165.     u_long vers;
  166. {
  167.     struct svc_callout *prev;
  168.     register struct svc_callout *s;
  169.  
  170.     if ((s = svc_find(prog, vers, &prev)) == NULL_SVC)
  171.         return;
  172.     if (prev == NULL_SVC) {
  173.         svc_head = s->sc_next;
  174.     } else {
  175.         prev->sc_next = s->sc_next;
  176.     }
  177.     s->sc_next = NULL_SVC;
  178.     mem_free(s, sizeof(struct svc_callout));
  179.     /* now unregister the information with the local binder service */
  180.     (void)pmap_unset(prog, vers);
  181. }
  182.  
  183. /*
  184.  * Search the callout list for a program number, return the callout
  185.  * struct.
  186.  */
  187. static 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.  
  195.     p = NULL_SVC;
  196.     for (s = 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.  
  206. /* ******************* REPLY GENERATION ROUTINES  ************ */
  207.  
  208. /*
  209.  * Send a reply to an rpc request
  210.  */
  211. bool_t
  212. svc_sendreply(xprt, xdr_results, xdr_location)
  213.     register SVCXPRT *xprt;
  214.     xdrproc_t xdr_results;
  215.     caddr_t xdr_location;
  216. {
  217.     struct rpc_msg rply; 
  218.  
  219.     rply.rm_direction = REPLY;  
  220.     rply.rm_reply.rp_stat = MSG_ACCEPTED; 
  221.     rply.acpted_rply.ar_verf = xprt->xp_verf; 
  222.     rply.acpted_rply.ar_stat = SUCCESS;
  223.     rply.acpted_rply.ar_results.where = xdr_location;
  224.     rply.acpted_rply.ar_results.proc = xdr_results;
  225.     return (SVC_REPLY(xprt, &rply)); 
  226. }
  227.  
  228. /*
  229.  * No procedure error reply
  230.  */
  231. void
  232. svcerr_noproc(xprt)
  233.     register SVCXPRT *xprt;
  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 = PROC_UNAVAIL;
  241.     SVC_REPLY(xprt, &rply);
  242. }
  243.  
  244. /*
  245.  * Can't decode args error reply
  246.  */
  247. void
  248. svcerr_decode(xprt)
  249.     register SVCXPRT *xprt;
  250. {
  251.     struct rpc_msg rply; 
  252.  
  253.     rply.rm_direction = REPLY; 
  254.     rply.rm_reply.rp_stat = MSG_ACCEPTED; 
  255.     rply.acpted_rply.ar_verf = xprt->xp_verf;
  256.     rply.acpted_rply.ar_stat = GARBAGE_ARGS;
  257.     SVC_REPLY(xprt, &rply); 
  258. }
  259.  
  260. /*
  261.  * Some system error
  262.  */
  263. void
  264. svcerr_systemerr(xprt)
  265.     register SVCXPRT *xprt;
  266. {
  267.     struct rpc_msg rply; 
  268.  
  269.     rply.rm_direction = REPLY; 
  270.     rply.rm_reply.rp_stat = MSG_ACCEPTED; 
  271.     rply.acpted_rply.ar_verf = xprt->xp_verf;
  272.     rply.acpted_rply.ar_stat = SYSTEM_ERR;
  273.     SVC_REPLY(xprt, &rply); 
  274. }
  275.  
  276. /*
  277.  * Authentication error reply
  278.  */
  279. void
  280. svcerr_auth(xprt, why)
  281.     SVCXPRT *xprt;
  282.     enum auth_stat why;
  283. {
  284.     struct rpc_msg rply;
  285.  
  286.     rply.rm_direction = REPLY;
  287.     rply.rm_reply.rp_stat = MSG_DENIED;
  288.     rply.rjcted_rply.rj_stat = AUTH_ERROR;
  289.     rply.rjcted_rply.rj_why = why;
  290.     SVC_REPLY(xprt, &rply);
  291. }
  292.  
  293. /*
  294.  * Auth too weak error reply
  295.  */
  296. void
  297. svcerr_weakauth(xprt)
  298.     SVCXPRT *xprt;
  299. {
  300.  
  301.     svcerr_auth(xprt, AUTH_TOOWEAK);
  302. }
  303.  
  304. /*
  305.  * Program unavailable error reply
  306.  */
  307. void 
  308. svcerr_noprog(xprt)
  309.     register SVCXPRT *xprt;
  310. {
  311.     struct rpc_msg rply;  
  312.  
  313.     rply.rm_direction = REPLY;   
  314.     rply.rm_reply.rp_stat = MSG_ACCEPTED;  
  315.     rply.acpted_rply.ar_verf = xprt->xp_verf;  
  316.     rply.acpted_rply.ar_stat = PROG_UNAVAIL;
  317.     SVC_REPLY(xprt, &rply);
  318. }
  319.  
  320. /*
  321.  * Program version mismatch error reply
  322.  */
  323. void  
  324. svcerr_progvers(xprt, low_vers, high_vers)
  325.     register SVCXPRT *xprt; 
  326.     u_long low_vers;
  327.     u_long high_vers;
  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_MISMATCH;
  335.     rply.acpted_rply.ar_vers.low = low_vers;
  336.     rply.acpted_rply.ar_vers.high = high_vers;
  337.     SVC_REPLY(xprt, &rply);
  338. }
  339.  
  340. /* ******************* SERVER INPUT STUFF ******************* */
  341.  
  342. /*
  343.  * Get server side input from some transport
  344.  */
  345. void
  346. svc_getreq(rdfds)
  347.     int rdfds;
  348. {
  349.     register int sock;
  350.     register int readfds = rdfds & svc_fds;
  351.     register SVCXPRT *xprt;
  352.     register enum xprt_stat stat;
  353.     struct rpc_msg msg;
  354.     /*char cred_body[MAX_AUTH_BYTES], verf_body[MAX_AUTH_BYTES];*/
  355.     char *cred_body;
  356.     int prog_found;
  357.     u_long low_vers;
  358.     u_long high_vers;
  359.  
  360.     cred_body = (char *)mem_alloc(2 * MAX_AUTH_BYTES);
  361.     if (cred_body == NULL) {
  362.         fprintf(stderr, "svc_getreq: out of memory\n");
  363.         svcerr_systemerr(xprt);
  364.         goto call_done;
  365.     }
  366.     msg.rm_call.cb_cred.oa_base = cred_body;
  367.     msg.rm_call.cb_verf.oa_base = &(cred_body[MAX_AUTH_BYTES]);
  368.     for (sock = 0; readfds != 0; sock++, readfds >>= 1) {
  369.         if ((readfds & 1) != 0) {
  370.         /* sock has input waiting */
  371.         xprt = xports[sock];
  372.         /* now receive msgs from xprtprt (support batch calls) */
  373.         do {
  374.             if (SVC_RECV(xprt, &msg)) {
  375.  
  376.                 /* now find the exported program and call it */
  377.                 register struct svc_callout *s;
  378.                 enum auth_stat why;
  379.                 struct svc_req r;
  380.  
  381.                 r.rq_xprt = xprt;
  382.                 r.rq_prog = msg.rm_call.cb_prog;
  383.                 r.rq_vers = msg.rm_call.cb_vers;
  384.                 r.rq_proc = msg.rm_call.cb_proc;
  385.                 r.rq_cred = msg.rm_call.cb_cred;
  386.                 /* first authenticate the message */
  387.                 if ((why= _authenticate(&r, &msg)) != AUTH_OK) {
  388.                     svcerr_auth(xprt, why);
  389.                     goto call_done;
  390.                 }
  391.                 /* now match message with a registered service*/
  392.                 prog_found = FALSE;
  393.                 low_vers = 0 - 1;
  394.                 high_vers = 0;
  395.                 for (s = svc_head; s != NULL_SVC; s = s->sc_next) {
  396.                     if (s->sc_prog == r.rq_prog) {
  397.                         if (s->sc_vers == r.rq_vers) {
  398.                             (*s->sc_dispatch)(&r, xprt);
  399.                             goto call_done;
  400.                         }  /* found correct version */
  401.                         prog_found = TRUE;
  402.                         if (s->sc_vers < low_vers)
  403.                             low_vers = s->sc_vers;
  404.                         if (s->sc_vers > high_vers)
  405.                             high_vers = s->sc_vers;
  406.                     }   /* found correct program */
  407.                 }
  408.                 /*
  409.                  * if we got here, the program or version
  410.                  * is not served ...
  411.                  */
  412.                 if (prog_found)
  413.                     svcerr_progvers(xprt,
  414.                     low_vers, high_vers);
  415.                 else
  416.                      svcerr_noprog(xprt);
  417.                 /* Fall through to ... */
  418.             }
  419.         call_done:
  420.             if ((stat = SVC_STAT(xprt)) == XPRT_DIED){
  421.                 SVC_DESTROY(xprt);
  422.                 break;
  423.             }
  424.         } while (stat == XPRT_MOREREQS);
  425.         }
  426.     }
  427.     mem_free(cred_body, 2 * MAX_AUTH_BYTES);
  428. }
  429.  
  430. /*
  431.  * This is the rpc server side idle loop
  432.  * Wait for input, call server program.
  433.  */
  434. void
  435. svc_run()
  436. {
  437.     int readfds;
  438.  
  439.     while (TRUE) {
  440.         readfds = svc_fds;
  441.         switch (select(32, &readfds, (int *)NULL, (int *)NULL,
  442.             (struct timeval *)NULL)) {
  443.  
  444.         case -1:
  445.                         if (errno == EINTR)
  446.                                 continue;
  447.                     else {
  448.                                 perror("svc.c: - Select failed");
  449.                                 return;
  450.             }
  451.         case 0:
  452.             continue;
  453.         default:
  454.             svc_getreq(readfds);
  455.         }
  456.     }
  457. }
  458.  
  459. /* *************************** BUILTIN TEST SERVICE **************** */
  460. void
  461. rpctest_service(reqst, xprt)
  462.     struct svc_req *reqst;
  463.     register SVCXPRT *xprt;
  464. {
  465.  
  466.     switch (reqst->rq_proc) {
  467.  
  468.     case RPCTEST_NULL_PROC:
  469.         /* get nullp parameters, return null results */
  470.         if (SVC_GETARGS(xprt, xdr_void, NULL)) {
  471.             svc_sendreply(xprt, (xdrproc_t)xdr_void, (caddr_t)NULL);
  472.         } else {
  473.             svcerr_decode(xprt);
  474.         }
  475.         return;
  476.  
  477.     case  RPCTEST_NULL_BATCH_PROC:  /* nothing !! */
  478.         return;
  479.  
  480.     default:
  481.         svcerr_noproc(xprt);
  482.         return;
  483.     }
  484. }
  485. !Funky!Stuff!
  486. echo x - svc.h
  487. sed 's/^X//' >svc.h <<'!Funky!Stuff!'
  488. /*
  489.  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  490.  * unrestricted use provided that this legend is included on all tape
  491.  * media and as a part of the software program in whole or part.  Users
  492.  * may copy or modify Sun RPC without charge, but are not authorized
  493.  * to license or distribute it to anyone else except as part of a product or
  494.  * program developed by the user.
  495.  * 
  496.  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  497.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  498.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  499.  * 
  500.  * Sun RPC is provided with no support and without any obligation on the
  501.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  502.  * modification or enhancement.
  503.  * 
  504.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  505.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  506.  * OR ANY PART THEREOF.
  507.  * 
  508.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  509.  * or profits or other special, indirect and consequential damages, even if
  510.  * Sun has been advised of the possibility of such damages.
  511.  * 
  512.  * Sun Microsystems, Inc.
  513.  * 2550 Garcia Avenue
  514.  * Mountain View, California  94043
  515.  */
  516. /*      @(#)svc.h 1.2 85/02/08 SMI      */
  517.  
  518. /*
  519.  * svc.h, Server-side remote procedure call interface.
  520.  *
  521.  * Copyright (C) 1984, Sun Microsystems, Inc.
  522.  */
  523.  
  524. /*
  525.  * This interface must manage two items concerning remote procedure calling:
  526.  *
  527.  * 1) An arbitrary number of transport connections upon which rpc requests
  528.  * are received.  The two most notable transports are TCP and UDP;  they are
  529.  * created and registered by routines in svc_tcp.c and svc_udp.c, respectively;
  530.  * they in turn call xprt_register and xprt_unregister.
  531.  *
  532.  * 2) An arbitrary number of locally registered services.  Services are
  533.  * described by the following four data: program number, version number,
  534.  * "service dispatch" function, a transport handle, and a boolean that
  535.  * indicates whether or not the exported program should be registered with a
  536.  * local binder service;  if true the program's number and version and the
  537.  * port number from the transport handle are registered with the binder.
  538.  * These data are registered with the rpc svc system via svc_register.
  539.  *
  540.  * A service's dispatch function is called whenever an rpc request comes in
  541.  * on a transport.  The request's program and version numbers must match
  542.  * those of the registered service.  The dispatch function is passed two
  543.  * parameters, struct svc_req * and SVCXPRT *, defined below.
  544.  */
  545.  
  546. enum xprt_stat {
  547.     XPRT_DIED,
  548.     XPRT_MOREREQS,
  549.     XPRT_IDLE
  550. };
  551.  
  552. /*
  553.  * Server side transport handle
  554.  */
  555. typedef struct {
  556.     int        xp_sock;
  557.     u_short        xp_port;     /* associated port number */
  558.     struct xp_ops {
  559.         bool_t    (*xp_recv)();     /* receive incomming requests */
  560.         enum xprt_stat (*xp_stat)(); /* get transport status */
  561.         bool_t    (*xp_getargs)(); /* get arguments */
  562.         bool_t    (*xp_reply)();     /* send reply */
  563.         bool_t    (*xp_freeargs)();/* free mem allocated for args */
  564.         void    (*xp_destroy)(); /* destroy this struct */
  565.     } *xp_ops;
  566.     int        xp_addrlen;     /* length of remote address */
  567.     struct sockaddr_in xp_raddr;     /* remote address */
  568.     struct opaque_auth xp_verf;     /* raw response verifier */
  569.     caddr_t        xp_p1;         /* private */
  570.     caddr_t        xp_p2;         /* private */
  571. } SVCXPRT;
  572.  
  573. /*
  574.  *  Approved way of getting address of caller
  575.  */
  576. #define svc_getcaller(x) (&(x)->xp_raddr)
  577.  
  578. /*
  579.  * Operations defined on an SVCXPRT handle
  580.  *
  581.  * SVCXPRT        *xprt;
  582.  * struct rpc_msg    *msg;
  583.  * xdrproc_t         xargs;
  584.  * caddr_t         argsp;
  585.  */
  586. #define SVC_RECV(xprt, msg)                \
  587.     (*(xprt)->xp_ops->xp_recv)((xprt), (msg))
  588. #define svc_recv(xprt, msg)                \
  589.     (*(xprt)->xp_ops->xp_recv)((xprt), (msg))
  590.  
  591. #define SVC_STAT(xprt)                    \
  592.     (*(xprt)->xp_ops->xp_stat)(xprt)
  593. #define svc_stat(xprt)                    \
  594.     (*(xprt)->xp_ops->xp_stat)(xprt)
  595.  
  596. #define SVC_GETARGS(xprt, xargs, argsp)            \
  597.     (*(xprt)->xp_ops->xp_getargs)((xprt), (xargs), (argsp))
  598. #define svc_getargs(xprt, xargs, argsp)            \
  599.     (*(xprt)->xp_ops->xp_getargs)((xprt), (xargs), (argsp))
  600.  
  601. #define SVC_REPLY(xprt, msg)                \
  602.     (*(xprt)->xp_ops->xp_reply) ((xprt), (msg))
  603. #define svc_reply(xprt, msg)                \
  604.     (*(xprt)->xp_ops->xp_reply) ((xprt), (msg))
  605.  
  606. #define SVC_FREEARGS(xprt, xargs, argsp)        \
  607.     (*(xprt)->xp_ops->xp_freeargs)((xprt), (xargs), (argsp))
  608. #define svc_freeargs(xprt, xargs, argsp)        \
  609.     (*(xprt)->xp_ops->xp_freeargs)((xprt), (xargs), (argsp))
  610.  
  611. #define SVC_DESTROY(xprt)                \
  612.     (*(xprt)->xp_ops->xp_destroy)(xprt)
  613. #define svc_destroy(xprt)                \
  614.     (*(xprt)->xp_ops->xp_destroy)(xprt)
  615.  
  616.  
  617. /*
  618.  * Service request
  619.  */
  620. struct svc_req {
  621.     u_long        rq_prog;    /* service program number */
  622.     u_long        rq_vers;    /* service protocol version */
  623.     u_long        rq_proc;    /* the desired procedure */
  624.     struct opaque_auth rq_cred;    /* raw creds from the wire */
  625.     caddr_t        rq_clntcred;    /* read only cooked cred */
  626.     SVCXPRT    *rq_xprt;        /* associated transport */
  627. };
  628.  
  629.  
  630. /*
  631.  * Service registration
  632.  *
  633.  * svc_register(xprt, prog, vers, dispatch, protocol)
  634.  *    SVCXPRT *xprt;
  635.  *    u_long prog;
  636.  *    u_long vers;
  637.  *    void (*dispatch)();
  638.  *    int protocol;  /* like TCP or UDP, zero means do not register 
  639.  */
  640. extern bool_t    svc_register();
  641.  
  642. /*
  643.  * Service un-registration
  644.  *
  645.  * svc_unregister(prog, vers)
  646.  *    u_long prog;
  647.  *    u_long vers;
  648.  */
  649. extern void    svc_unregister();
  650.  
  651. /*
  652.  * Transport registration.
  653.  *
  654.  * xprt_register(xprt)
  655.  *    SVCXPRT *xprt;
  656.  */
  657. extern void    xprt_register();
  658.  
  659. /*
  660.  * Transport un-register
  661.  *
  662.  * xprt_unregister(xprt)
  663.  *    SVCXPRT *xprt;
  664.  */
  665. extern void    xprt_unregister();
  666.  
  667.  
  668. /*
  669.  * When the service routine is called, it must first check to see if it
  670.  * knows about the procedure;  if not, it should call svcerr_noproc
  671.  * and return.  If so, it should deserialize its arguments via 
  672.  * SVC_GETARGS (defined above).  If the deserialization does not work,
  673.  * svcerr_decode should be called followed by a return.  Successful
  674.  * decoding of the arguments should be followed the execution of the
  675.  * procedure's code and a call to svc_sendreply.
  676.  *
  677.  * Also, if the service refuses to execute the procedure due to too-
  678.  * weak authentication parameters, svcerr_weakauth should be called.
  679.  * Note: do not confuse access-control failure with weak authentication!
  680.  *
  681.  * NB: In pure implementations of rpc, the caller always waits for a reply
  682.  * msg.  This message is sent when svc_sendreply is called.  
  683.  * Therefore pure service implementations should always call
  684.  * svc_sendreply even if the function logically returns void;  use
  685.  * xdr.h - xdr_void for the xdr routine.  HOWEVER, tcp based rpc allows
  686.  * for the abuse of pure rpc via batched calling or pipelining.  In the
  687.  * case of a batched call, svc_sendreply should NOT be called since
  688.  * this would send a return message, which is what batching tries to avoid.
  689.  * It is the service/protocol writer's responsibility to know which calls are
  690.  * batched and which are not.  Warning: responding to batch calls may
  691.  * deadlock the caller and server processes!
  692.  */
  693.  
  694. extern bool_t  svc_sendreply();
  695. extern void    svcerr_noproc();
  696. extern void    svcerr_decode();
  697. extern void    svcerr_weakauth();
  698.  
  699. /*
  700.  * Lowest level dispatching -OR- who owns this process anyway.
  701.  * Somebody has to wait for incoming requests and then call the correct
  702.  * service routine.  The routine svc_run does infinite waiting; i.e.,
  703.  * svc_run never returns.
  704.  * Since another (co-existant) package may wish to selectively wait for
  705.  * incoming calls or other events outside of the rpc architecture, the
  706.  * routine svc_getreq is provided.  It must be passed readfds, the
  707.  * "in-place" results of a select system call (see select, section 2).
  708.  */
  709.  
  710. /* dynamic; must be inspected before each call to select */
  711. extern int svc_fds;
  712.  
  713. extern void    svc_getreq();
  714. extern void    svc_run();  /* never returns */
  715.  
  716. /*
  717.  * a small program implemented by the svc_rpc implementation itself;
  718.  * also see clnt.h for protocol numbers.
  719.  */
  720. extern void rpctest_service();
  721.  
  722. /*
  723.  * Socket to use on svcxxx_create call to get default socket
  724.  */
  725. #define    RPC_ANYSOCK    -1
  726.  
  727. /*
  728.  * These are the existing service side transport implementations
  729.  */
  730.  
  731. /*
  732.  * Memory based rpc for testing and timing.
  733.  */
  734. extern SVCXPRT *svcraw_create();
  735.  
  736. /*
  737.  * Udp based rpc.
  738.  */
  739. extern SVCXPRT *svcudp_create();
  740.  
  741. /*
  742.  * Tcp based rpc.
  743.  */
  744. extern SVCXPRT *svctcp_create();
  745.  
  746. !Funky!Stuff!
  747. echo x - svc_auth.c
  748. sed 's/^X//' >svc_auth.c <<'!Funky!Stuff!'
  749. /*
  750.  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  751.  * unrestricted use provided that this legend is included on all tape
  752.  * media and as a part of the software program in whole or part.  Users
  753.  * may copy or modify Sun RPC without charge, but are not authorized
  754.  * to license or distribute it to anyone else except as part of a product or
  755.  * program developed by the user.
  756.  * 
  757.  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  758.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  759.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  760.  * 
  761.  * Sun RPC is provided with no support and without any obligation on the
  762.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  763.  * modification or enhancement.
  764.  * 
  765.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  766.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  767.  * OR ANY PART THEREOF.
  768.  * 
  769.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  770.  * or profits or other special, indirect and consequential damages, even if
  771.  * Sun has been advised of the possibility of such damages.
  772.  * 
  773.  * Sun Microsystems, Inc.
  774.  * 2550 Garcia Avenue
  775.  * Mountain View, California  94043
  776.  */
  777. #ifndef lint
  778. static char sccsid[] = "@(#)svc_auth.c 1.4 85/03/17 Copyr 1984 Sun Micro";
  779. #endif
  780.  
  781. /*
  782.  * svc_auth.c, Server-side rpc authenticator interface.
  783.  *
  784.  * Copyright (C) 1984, Sun Microsystems, Inc.
  785.  */
  786.  
  787. #include "types.h"
  788. #include <netinet/in.h>
  789. #include "xdr.h"
  790. #include "auth.h"
  791. #include "clnt.h"
  792. #include "rpc_msg.h"
  793. #include "svc.h"
  794. #include "svc_auth.h"
  795.  
  796. /*
  797.  * svcauthsw is the bdevsw of server side authentication. 
  798.  * 
  799.  * Server side authenticators are called from authenticate by
  800.  * using the client auth struct flavor field to index into svcauthsw.
  801.  * The server auth flavors must implement a routine that looks  
  802.  * like: 
  803.  * 
  804.  *    enum auth_stat 
  805.  *    flavorx_auth(rqst, msg)
  806.  *        register struct svc_req *rqst; 
  807.  *        register struct rpc_msg *msg;
  808.  *  
  809.  */
  810.  
  811. enum auth_stat _svcauth_null();        /* no authentication */
  812. enum auth_stat _svcauth_unix();        /* unix style (uid, gids) */
  813. enum auth_stat _svcauth_short();        /* short hand unix style */
  814.  
  815. static struct {
  816.     enum auth_stat (*authenticator)();
  817. } svcauthsw[] = {
  818.     _svcauth_null,            /* AUTH_NULL */
  819.     _svcauth_unix,            /* AUTH_UNIX */
  820.     _svcauth_short            /* AUTH_SHORT */
  821. };
  822. #define    AUTH_MAX    2        /* HIGHEST AUTH NUMBER */
  823.  
  824.  
  825. /*
  826.  * The call rpc message, msg has been obtained from the wire.  The msg contains
  827.  * the raw form of credentials and verifiers.  authenticate returns AUTH_OK
  828.  * if the msg is successfully authenticated.  If AUTH_OK then the routine also
  829.  * does the following things:
  830.  * set rqst->rq_xprt->verf to the appropriate response verifier;
  831.  * sets rqst->rq_client_cred to the "cooked" form of the credentials.
  832.  *
  833.  * NB: rqst->rq_cxprt->verf must be pre-alloctaed;
  834.  * its length is set appropriately.
  835.  *
  836.  * The caller still owns and is responsible for msg->u.cmb.cred and
  837.  * msg->u.cmb.verf.  The authentication system retains ownership of
  838.  * rqst->rq_client_cred, the cooked credentials.
  839.  */
  840. enum auth_stat
  841. _authenticate(rqst, msg)
  842.     register struct svc_req *rqst;
  843.     struct rpc_msg *msg;
  844. {
  845.     register int cred_flavor;
  846.  
  847.     rqst->rq_cred = msg->rm_call.cb_cred;
  848.     rqst->rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor;
  849.     rqst->rq_xprt->xp_verf.oa_length = 0;
  850.     rqst->rq_clntcred = (caddr_t)AUTH_NULL;
  851.     cred_flavor = rqst->rq_cred.oa_flavor;
  852.     if (cred_flavor <= AUTH_MAX) {
  853.         return ((*(svcauthsw[cred_flavor].authenticator))(rqst, msg));
  854.     }
  855.  
  856.     return (AUTH_REJECTEDCRED);
  857. }
  858.  
  859. enum auth_stat
  860. _svcauth_null(/*rqst, msg*/)
  861.     /*struct svc_req *rqst;
  862.     struct rpc_msg *msg;*/
  863. {
  864.  
  865.     return (AUTH_OK);
  866. }
  867. !Funky!Stuff!
  868. echo x - svc_auth.h
  869. sed 's/^X//' >svc_auth.h <<'!Funky!Stuff!'
  870. /*
  871.  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  872.  * unrestricted use provided that this legend is included on all tape
  873.  * media and as a part of the software program in whole or part.  Users
  874.  * may copy or modify Sun RPC without charge, but are not authorized
  875.  * to license or distribute it to anyone else except as part of a product or
  876.  * program developed by the user.
  877.  * 
  878.  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  879.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  880.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  881.  * 
  882.  * Sun RPC is provided with no support and without any obligation on the
  883.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  884.  * modification or enhancement.
  885.  * 
  886.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  887.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  888.  * OR ANY PART THEREOF.
  889.  * 
  890.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  891.  * or profits or other special, indirect and consequential damages, even if
  892.  * Sun has been advised of the possibility of such damages.
  893.  * 
  894.  * Sun Microsystems, Inc.
  895.  * 2550 Garcia Avenue
  896.  * Mountain View, California  94043
  897.  */
  898. /*      @(#)svc_auth.h 1.2 85/03/14 SMI      */
  899.  
  900. /*
  901.  * svc_auth.h, Service side of rpc authentication.
  902.  * 
  903.  * Copyright (C) 1984, Sun Microsystems, Inc.
  904.  */
  905.  
  906.  
  907. /*
  908.  * Server side authenticator
  909.  */
  910. extern enum auth_stat _authenticate();
  911. !Funky!Stuff!
  912. echo x - svc_auth_unix.c
  913. sed 's/^X//' >svc_auth_unix.c <<'!Funky!Stuff!'
  914. /*
  915.  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  916.  * unrestricted use provided that this legend is included on all tape
  917.  * media and as a part of the software program in whole or part.  Users
  918.  * may copy or modify Sun RPC without charge, but are not authorized
  919.  * to license or distribute it to anyone else except as part of a product or
  920.  * program developed by the user.
  921.  * 
  922.  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  923.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  924.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  925.  * 
  926.  * Sun RPC is provided with no support and without any obligation on the
  927.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  928.  * modification or enhancement.
  929.  * 
  930.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  931.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  932.  * OR ANY PART THEREOF.
  933.  * 
  934.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  935.  * or profits or other special, indirect and consequential damages, even if
  936.  * Sun has been advised of the possibility of such damages.
  937.  * 
  938.  * Sun Microsystems, Inc.
  939.  * 2550 Garcia Avenue
  940.  * Mountain View, California  94043
  941.  */
  942. #ifndef lint
  943. static char sccsid[] = "@(#)svc_auth_unix.c 1.4 85/03/14 Copyr 1984 Sun Micro";
  944. #endif
  945.  
  946. /*
  947.  * svc_auth_unix.c
  948.  * Handles UNIX flavor authentication parameters on the service side of rpc.
  949.  * There are two svc auth implementations here: AUTH_UNIX and AUTH_SHORT.
  950.  * _svcauth_unix does full blown unix style uid,gid+gids auth,
  951.  * _svcauth_short uses a shorthand auth to index into a cache of longhand auths.
  952.  *
  953.  * Copyright (C) 1984, Sun Microsystems, Inc.
  954.  */
  955.  
  956. #include <stdio.h>
  957. #include "types.h"
  958. #include <sys/time.h>
  959. #include <netinet/in.h>
  960. #include "xdr.h"
  961. #include "auth.h"
  962. #include "clnt.h"
  963. #include "rpc_msg.h"
  964. #include "svc.h"
  965. #include "auth_unix.h"
  966. #include "svc_auth.h"
  967. char *mem_alloc();
  968.  
  969. #define SHORT_VERF_SIZE (3 * BYTES_PER_XDR_UNIT)
  970. #define CACHE_SIZE 16
  971.  
  972. static struct cache_entry {
  973.     u_long        sh;        /* short hand value */
  974. #define SHORT_CRED_SIZE (sizeof (u_long))
  975.     short        cred_len;    /* byte length of opaque credential */
  976.     caddr_t        cred_base;    /* the opaque credential body */
  977.     struct authunix_parms aup;    /* cooked, deserialized credentials */
  978. } cache[CACHE_SIZE];
  979.  
  980. static short cacheindex[CACHE_SIZE];
  981.  
  982. /*
  983.  * Cache handling macros
  984.  */
  985. #define valid_aup(aup) (TRUE)
  986. #define nexti(i)  ((i == CACHE_SIZE-1) ? 0 : i+1)
  987. #define previ(i)  ((i == 0) ? CACHE_SIZE-1 : i-1)
  988. #define cache_hit(c, d) \
  989.    ( hits++, d=cnt-c, depth += d, maxdepth = (d > maxdepth) ? d: maxdepth )
  990.  
  991. /*
  992.  * Cache handling routines
  993.  */
  994. static short    find_short_hand();
  995. static short    find_long_hand();
  996.  
  997. /*
  998.  * Cache variables
  999.  */
  1000. static short head, maxdepth;    /* values from 0 to CACHE_SIZE-1, inclusive */
  1001. static short cnt;        /*  values from 0 to CACHE_SIZE, inclusive */
  1002. static u_long additions, deletions, queries, hits, depth;
  1003. static struct timeval last_time;
  1004. static inited = 0;        /* stupid kludge to be sure init gets called */
  1005.  
  1006.  
  1007. /*
  1008.  * Unix longhand authenticator
  1009.  */
  1010. enum auth_stat
  1011. _svcauth_unix(rqst, msg)
  1012.     register struct svc_req *rqst;
  1013.     register struct rpc_msg *msg;
  1014. {
  1015.     register short i = -1;
  1016.     register int len = msg->rm_call.cb_cred.oa_length;
  1017.     register caddr_t base = msg->rm_call.cb_cred.oa_base;
  1018.     register enum auth_stat stat = AUTH_OK;
  1019.     XDR xdrs;
  1020.     struct authunix_parms aup;
  1021.     struct opaque_auth short_cred;
  1022.  
  1023.     if (!inited) {
  1024.         svcauth_unix_init();
  1025.     }
  1026.     while ((i = find_long_hand(base, len)) < 0) {
  1027.         /* deserialize credentials */
  1028.         aup.aup_machname = NULL;
  1029.         aup.aup_gids = (int *)NULL;
  1030.         xdrmem_create(&xdrs, base, (u_int)len, XDR_DECODE); 
  1031.         if (! (xdr_authunix_parms(&xdrs, &aup) && valid_aup(&aup))) {
  1032.             xdrs.x_op = XDR_FREE;
  1033.             (void)xdr_authunix_parms(&xdrs, &aup);
  1034.             stat = AUTH_BADCRED;
  1035.             goto done;
  1036.         }
  1037.         /* now make a new cache entry for this credential */
  1038.         cache_new_user(base, len, &aup);
  1039.     }
  1040.     rqst->rq_clntcred = (caddr_t)&(cache[i].aup);
  1041.     /* now build a verifier that suggests using the short hand credential */
  1042.     short_cred.oa_flavor = AUTH_SHORT;
  1043.     short_cred.oa_length = SHORT_CRED_SIZE;
  1044.     short_cred.oa_base = (caddr_t)&(cache[i].sh);
  1045.     /* the short hand cred get serialized into a verifier */
  1046.     xdrmem_create(&xdrs, rqst->rq_xprt->xp_verf.oa_base,
  1047.         SHORT_VERF_SIZE, XDR_ENCODE);
  1048.     if (! xdr_opaque_auth(&xdrs, &short_cred)) {
  1049.         stat = AUTH_BADCRED;
  1050.         goto done;
  1051.     }
  1052.     rqst->rq_xprt->xp_verf.oa_length = XDR_GETPOS(&xdrs);
  1053.     rqst->rq_xprt->xp_verf.oa_flavor = AUTH_SHORT;
  1054. done:
  1055.     XDR_DESTROY(&xdrs);
  1056.     return (stat);
  1057. }
  1058.  
  1059.  
  1060. /*
  1061.  * Shorthand unix authenticator
  1062.  * Looks up longhand in a cache.
  1063.  */
  1064. enum auth_stat 
  1065. _svcauth_short(rqst, msg)
  1066.     struct svc_req *rqst;
  1067.     struct rpc_msg *msg;
  1068. {
  1069.     short i;
  1070.  
  1071.     if (!inited) {
  1072.         svcauth_unix_init();
  1073.     }
  1074.     if (msg->rm_call.cb_cred.oa_length != SHORT_CRED_SIZE)
  1075.         return (AUTH_BADCRED);
  1076.     if ((i = find_short_hand(*(u_long *)msg->rm_call.cb_cred.oa_base)) < 0)
  1077.         return (AUTH_REJECTEDCRED);
  1078.     rqst->rq_clntcred = (caddr_t)&(cache[i].aup);
  1079.     return (AUTH_OK);
  1080. }
  1081.  
  1082.  
  1083. /*
  1084.  * returns cache index or -1 if sh not in the cache
  1085.  */
  1086. static short
  1087. find_short_hand(sh)
  1088.     register u_long sh;  /* short hand value */
  1089. {
  1090.     /* declared in order of importance */
  1091.     register short entry, i, c, p;
  1092.  
  1093.     queries++;
  1094.     for (c = cnt, i = head; c > 0; --c, i = nexti(i)) {
  1095.  
  1096.         entry = cacheindex[i];
  1097.         if (sh == cache[entry].sh) {
  1098.             /* cache hit! Now buble swap i up one notch */
  1099.             cache_hit(c, p);  /* used for accounting only */
  1100.             if (i != head) {
  1101.                 /* c acts as the temporary variable */
  1102.                 p = previ(i);
  1103.                 c = cacheindex[p];
  1104.                 cacheindex[p] = entry; /* gets cacheindex[i] */
  1105.                 cacheindex[i] = c;
  1106.             }
  1107.             return (entry);
  1108.         }  /* end of successful cache hit */
  1109.     }
  1110.     return (-1);
  1111. }
  1112.  
  1113. /*
  1114.  * returns cache index or -1 if cred not in the cache
  1115.  */
  1116. static short
  1117. find_long_hand(cred_base, len)
  1118.     register caddr_t cred_base;
  1119.     register int len;
  1120. {
  1121.     /* declared in order of importance */
  1122.     register short entry, i, c, p;
  1123.  
  1124.     queries++;
  1125.     for (c = cnt, i = head; c > 0; --c, i = nexti(i)) {
  1126.  
  1127.         entry = cacheindex[i];
  1128.         if ((cache[entry].cred_len == len) &&
  1129.             (bcmp(cache[entry].cred_base, cred_base, len) == 0)) {
  1130.             /* cache hit! Now buble swap i up one notch */
  1131.             cache_hit(c, p);  /* used for accounting only */
  1132.             if (i != head) {
  1133.                 /* c acts as the temporary variable */
  1134.                 p = previ(i);
  1135.                 c = cacheindex[p];
  1136.                 cacheindex[p] = entry; /* gets cacheindex[i] */
  1137.                 cacheindex[i] = c;
  1138.             }
  1139.         return (entry);
  1140.         }  /* end of successful cache hit */
  1141.     }
  1142.     return (-1);
  1143. }
  1144.  
  1145. /*
  1146.  * Place a new entry at the HEAD of the cache.  This means moving the
  1147.  * heap index back one and possibly flushing the oldest entry from the cache.
  1148.  */
  1149. static
  1150. cache_new_user(base, len, aup)
  1151.     caddr_t base;
  1152.     int len;
  1153.     struct authunix_parms *aup;
  1154. {
  1155.     register short entry;
  1156.     struct timeval now;
  1157.  
  1158.     head = previ(head);
  1159.     entry = cacheindex[head];
  1160.     if (cnt == CACHE_SIZE) { /* full cache, delete lru entry */
  1161.         XDR xdrs;
  1162.  
  1163.         xdrs.x_op = XDR_FREE;
  1164.         deletions++;
  1165.         if (cache[entry].cred_base != NULL) {
  1166.             mem_free(cache[entry].cred_base,
  1167.                 cache[entry].cred_len);
  1168.             cache[entry].cred_base = NULL;
  1169.         }
  1170.         (void)xdr_authunix_parms(&xdrs, &cache[entry].aup);
  1171.     } else {
  1172.         cnt++;
  1173.     }
  1174.     /* now add current entry, raw cred must be copied */
  1175.     additions++;
  1176.     cache[entry].aup = *aup;
  1177.     cache[entry].cred_len = len;
  1178.     if ((cache[entry].cred_base = (char *)mem_alloc(len)) == NULL) {
  1179.         fprintf(stderr, "cache_new_user: out of memory\n");
  1180.         additions--;
  1181.         return;
  1182.     }
  1183.     bcopy(base, cache[entry].cred_base, (u_int)len);
  1184.     /* finally compute a new, unique short hand value */
  1185.     cache[entry].sh = ++ last_time.tv_sec;
  1186.     /* don't let real time get ahead of last_time */
  1187.     while (TRUE) {
  1188.         (void)gettimeofday(&now, (struct timezone *)0);
  1189.         if (((long int)now.tv_sec - (long int)last_time.tv_sec) > 0)
  1190.             break;
  1191.         sleep(1);
  1192.     }
  1193. }
  1194.  
  1195. /*
  1196.  * Initialize the shorthand cache.
  1197.  * Must be called before unix auth can be used!
  1198.  */
  1199. static svcauth_unix_init()
  1200. {
  1201.     register short i;
  1202.  
  1203.     inited++;
  1204.     (void)gettimeofday(&last_time, (struct timezone *)0);
  1205.     for (i = 0; i < CACHE_SIZE; ++i) {
  1206.         cacheindex[i] = i;
  1207.     }
  1208. }
  1209. !Funky!Stuff!
  1210. echo x - svc_raw.c
  1211. sed 's/^X//' >svc_raw.c <<'!Funky!Stuff!'
  1212. /*
  1213.  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  1214.  * unrestricted use provided that this legend is included on all tape
  1215.  * media and as a part of the software program in whole or part.  Users
  1216.  * may copy or modify Sun RPC without charge, but are not authorized
  1217.  * to license or distribute it to anyone else except as part of a product or
  1218.  * program developed by the user.
  1219.  * 
  1220.  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  1221.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  1222.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  1223.  * 
  1224.  * Sun RPC is provided with no support and without any obligation on the
  1225.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  1226.  * modification or enhancement.
  1227.  * 
  1228.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  1229.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  1230.  * OR ANY PART THEREOF.
  1231.  * 
  1232.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  1233.  * or profits or other special, indirect and consequential damages, even if
  1234.  * Sun has been advised of the possibility of such damages.
  1235.  * 
  1236.  * Sun Microsystems, Inc.
  1237.  * 2550 Garcia Avenue
  1238.  * Mountain View, California  94043
  1239.  */
  1240. #ifndef lint
  1241. static char sccsid[] = "@(#)svc_raw.c 1.3 85/03/14 Copyr 1984 Sun Micro";
  1242. #endif
  1243.  
  1244. /*
  1245.  * svc_raw.c,   This a toy for simple testing and timing.
  1246.  * Interface to create an rpc client and server in the same UNIX process.
  1247.  * This lets us similate rpc and get rpc (round trip) overhead, without
  1248.  * any interference from the kernal.
  1249.  *
  1250.  * Copyright (C) 1984, Sun Microsystems, Inc.
  1251.  */
  1252.  
  1253. #include "types.h"
  1254. #include <netinet/in.h>
  1255. #include "xdr.h"
  1256. #include "auth.h"
  1257. #include "clnt.h"
  1258. #include "rpc_msg.h"
  1259. #include "svc.h"
  1260.  
  1261. #define NULL ((caddr_t)0)
  1262.  
  1263. /*
  1264.  * This is the "network" that we will be moving data over
  1265.  */
  1266. extern char _raw_buf[UDPMSGSIZE];
  1267.  
  1268. static bool_t        svcraw_recv();
  1269. static enum xprt_stat     svcraw_stat();
  1270. static bool_t        svcraw_getargs();
  1271. static bool_t        svcraw_reply();
  1272. static bool_t        svcraw_freeargs();
  1273. static void        svcraw_destroy();
  1274.  
  1275. static struct xp_ops server_ops = {
  1276.     svcraw_recv,
  1277.     svcraw_stat,
  1278.     svcraw_getargs,
  1279.     svcraw_reply,
  1280.     svcraw_freeargs,
  1281.     svcraw_destroy
  1282. };
  1283.  
  1284. static SVCXPRT server;
  1285. static XDR xdr_stream;
  1286. static char verf_body[MAX_AUTH_BYTES];
  1287.  
  1288. SVCXPRT *
  1289. svcraw_create()
  1290. {
  1291.  
  1292.     server.xp_sock = 0;
  1293.     server.xp_port = 0;
  1294.     server.xp_ops = &server_ops;
  1295.     server.xp_verf.oa_base = verf_body;
  1296.     xdrmem_create(&xdr_stream, _raw_buf, UDPMSGSIZE, XDR_FREE);
  1297.     return (&server);
  1298. }
  1299.  
  1300. static enum xprt_stat
  1301. svcraw_stat()
  1302. {
  1303.  
  1304.     return (XPRT_IDLE);
  1305. }
  1306.  
  1307. static bool_t
  1308. svcraw_recv(xprt, msg)
  1309.     SVCXPRT *xprt;
  1310.     struct rpc_msg *msg;
  1311. {
  1312.     register XDR *xdrs = &xdr_stream;
  1313.  
  1314.     xdrs->x_op = XDR_DECODE;
  1315.     XDR_SETPOS(xdrs, 0);
  1316.     if (! xdr_callmsg(xdrs, msg))
  1317.            return (FALSE);
  1318.     return (TRUE);
  1319. }
  1320.  
  1321. static bool_t
  1322. svcraw_reply(xprt, msg)
  1323.     SVCXPRT *xprt;
  1324.     struct rpc_msg *msg;
  1325. {
  1326.     register XDR *xdrs = &xdr_stream;
  1327.  
  1328.     xdrs->x_op = XDR_ENCODE;
  1329.     XDR_SETPOS(xdrs, 0);
  1330.     if (! xdr_replymsg(xdrs, msg))
  1331.            return (FALSE);
  1332.     (void)XDR_GETPOS(xdrs);  /* called just for overhead */
  1333.     return (TRUE);
  1334. }
  1335.  
  1336. static bool_t
  1337. svcraw_getargs(xprt, xdr_args, args_ptr)
  1338.     SVCXPRT *xprt;
  1339.     xdrproc_t xdr_args;
  1340.     caddr_t args_ptr;
  1341. {
  1342.  
  1343.     return ((*xdr_args)(&xdr_stream, args_ptr));
  1344. }
  1345.  
  1346. static bool_t
  1347. svcraw_freeargs(xprt, xdr_args, args_ptr)
  1348.     SVCXPRT *xprt;
  1349.     xdrproc_t xdr_args;
  1350.     caddr_t args_ptr;
  1351.     register XDR *xdrs = &xdr_stream;
  1352.  
  1353.     xdrs->x_op = XDR_FREE;
  1354.     return ((*xdr_args)(xdrs, args_ptr));
  1355.  
  1356. static void
  1357. svcraw_destroy()
  1358. {
  1359. }
  1360. !Funky!Stuff!
  1361. echo x - svc_simple.c
  1362. sed 's/^X//' >svc_simple.c <<'!Funky!Stuff!'
  1363. /*
  1364.  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  1365.  * unrestricted use provided that this legend is included on all tape
  1366.  * media and as a part of the software program in whole or part.  Users
  1367.  * may copy or modify Sun RPC without charge, but are not authorized
  1368.  * to license or distribute it to anyone else except as part of a product or
  1369.  * program developed by the user.
  1370.  * 
  1371.  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  1372.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  1373.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  1374.  * 
  1375.  * Sun RPC is provided with no support and without any obligation on the
  1376.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  1377.  * modification or enhancement.
  1378.  * 
  1379.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  1380.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  1381.  * OR ANY PART THEREOF.
  1382.  * 
  1383.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  1384.  * or profits or other special, indirect and consequential damages, even if
  1385.  * Sun has been advised of the possibility of such damages.
  1386.  * 
  1387.  * Sun Microsystems, Inc.
  1388.  * 2550 Garcia Avenue
  1389.  * Mountain View, California  94043
  1390.  */
  1391. #ifndef lint
  1392. static char sccsid[] = "@(#)svc_simple.c 1.3 85/03/14 Copyr 1984 Sun Micro";
  1393. #endif
  1394.  
  1395. /* 
  1396.  * svc_simple.c
  1397.  * Simplified front end to rpc.
  1398.  *
  1399.  * Copyright (C) 1984, Sun Microsystems, Inc.
  1400.  */
  1401.  
  1402. #include <stdio.h>
  1403. #include <rpc/rpc.h>
  1404. #include <sys/socket.h>
  1405. #include <sys/time.h>
  1406. #include <netdb.h>
  1407.  
  1408. static struct proglst {
  1409.     char *(*p_progname)();
  1410.     int  p_prognum;
  1411.     int  p_procnum;
  1412.     xdrproc_t p_inproc, p_outproc;
  1413.     struct proglst *p_nxt;
  1414. } *proglst;
  1415. int universal();
  1416.  
  1417. registerrpc(prognum, versnum, procnum, progname, inproc, outproc)
  1418.     char *(*progname)();
  1419.     xdrproc_t inproc, outproc;
  1420. {
  1421.     static SVCXPRT *transp;
  1422.     static madetransp = 0;
  1423.     struct proglst *pl;
  1424.     
  1425.     if (procnum == NULLPROC) {
  1426.         fprintf(stderr,
  1427.             "can't reassign procedure number %d\n", NULLPROC);
  1428.         return (-1);
  1429.     }
  1430.     if (!madetransp) {
  1431.         madetransp = 1;
  1432.         transp = svcudp_create(RPC_ANYSOCK);
  1433.         if (transp == NULL) {
  1434.             fprintf(stderr, "couldn't create an rpc server\n");
  1435.             return (-1);
  1436.         }
  1437.     }
  1438.     pmap_unset(prognum, versnum);
  1439.     if (!svc_register(transp, prognum, versnum, universal, IPPROTO_UDP)) {
  1440.             fprintf(stderr, "couldn't register prog %d vers %d\n",
  1441.             prognum, versnum);
  1442.         return (-1);
  1443.     }
  1444.     pl = (struct proglst *)malloc(sizeof(struct proglst));
  1445.     if (pl == NULL) {
  1446.         fprintf(stderr, "registerrpc: out of memory\n");
  1447.         return (-1);
  1448.     }
  1449.     pl->p_progname = progname;
  1450.     pl->p_prognum = prognum;
  1451.     pl->p_procnum = procnum;
  1452.     pl->p_inproc = inproc;
  1453.     pl->p_outproc = outproc;
  1454.     pl->p_nxt = proglst;
  1455.     proglst = pl;
  1456.     return (0);
  1457. }
  1458.  
  1459. static
  1460. universal(rqstp, transp)
  1461.     struct svc_req *rqstp;
  1462.     SVCXPRT *transp;
  1463. {
  1464.     int prog, proc, i;
  1465.     char *outdata;
  1466.     char xdrbuf[UDPMSGSIZE];
  1467.     struct proglst *pl;
  1468.  
  1469.     /* 
  1470.      * enforce "procnum 0 is echo" convention
  1471.      */
  1472.     if (rqstp->rq_proc == NULLPROC) {
  1473.         if (svc_sendreply(transp, xdr_void, 0) == FALSE) {
  1474.             fprintf(stderr, "xxx\n");
  1475.             exit(1);
  1476.         }
  1477.         return;
  1478.     }
  1479.     prog = rqstp->rq_prog;
  1480.     proc = rqstp->rq_proc;
  1481.     for (pl = proglst; pl != NULL; pl = pl->p_nxt)
  1482.         if (pl->p_prognum == prog && pl->p_procnum == proc) {
  1483.             /* decode arguments into a CLEAN buffer */
  1484.             bzero(xdrbuf, sizeof(xdrbuf)); /* required ! */
  1485.             if (!svc_getargs(transp, pl->p_inproc, xdrbuf)) {
  1486.                 svcerr_decode(transp);
  1487.                 return;
  1488.             }
  1489.             outdata = (*(pl->p_progname))(xdrbuf);
  1490.             if (outdata == NULL && pl->p_outproc != xdr_void)
  1491.                 /* there was an error */
  1492.                 return;
  1493.             if (!svc_sendreply(transp, pl->p_outproc, outdata)) {
  1494.                 fprintf(stderr,
  1495.                     "trouble replying to prog %d\n",
  1496.                     pl->p_prognum);
  1497.                 exit(1);
  1498.             /* free the decoded arguments */
  1499.             (void)svc_freeargs(transp, pl->p_inproc, xdrbuf);
  1500.             }
  1501.             return;
  1502.         }
  1503.     fprintf(stderr, "never registered prog %d\n", prog);
  1504.     exit(1);
  1505. }
  1506.  
  1507. !Funky!Stuff!
  1508. echo x - svc_tcp.c
  1509. sed 's/^X//' >svc_tcp.c <<'!Funky!Stuff!'
  1510. /*
  1511.  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  1512.  * unrestricted use provided that this legend is included on all tape
  1513.  * media and as a part of the software program in whole or part.  Users
  1514.  * may copy or modify Sun RPC without charge, but are not authorized
  1515.  * to license or distribute it to anyone else except as part of a product or
  1516.  * program developed by the user.
  1517.  * 
  1518.  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  1519.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  1520.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  1521.  * 
  1522.  * Sun RPC is provided with no support and without any obligation on the
  1523.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  1524.  * modification or enhancement.
  1525.  * 
  1526.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  1527.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  1528.  * OR ANY PART THEREOF.
  1529.  * 
  1530.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  1531.  * or profits or other special, indirect and consequential damages, even if
  1532.  * Sun has been advised of the possibility of such damages.
  1533.  * 
  1534.  * Sun Microsystems, Inc.
  1535.  * 2550 Garcia Avenue
  1536.  * Mountain View, California  94043
  1537.  */
  1538. #ifndef lint
  1539. static char sccsid[] = "@(#)svc_tcp.c 1.5 85/03/17 Copyr 1984 Sun Micro";
  1540. #endif
  1541.  
  1542. /*
  1543.  * svc_tcp.c, Server side for TCP/IP based RPC. 
  1544.  *
  1545.  * Copyright (C) 1984, Sun Microsystems, Inc.
  1546.  *
  1547.  * Actually implements two flavors of transporter -
  1548.  * a tcp rendezvouser (a listner and connection establisher)
  1549.  * and a record/tcp stream.
  1550.  */
  1551.  
  1552. #include <stdio.h>
  1553. #include "types.h"
  1554. #include <netinet/in.h>
  1555. #include <sys/socket.h>
  1556. #include <sys/time.h>
  1557. #include <errno.h>
  1558. #include "xdr.h"
  1559. #include "auth.h"
  1560. #include "clnt.h"
  1561. #include "rpc_msg.h"
  1562. #include "svc.h"
  1563. char *mem_alloc();
  1564. extern bool_t abort();
  1565. extern errno;
  1566.  
  1567. /*
  1568.  * Ops vector for TCP/IP based rpc service handle
  1569.  */
  1570. static bool_t        svctcp_recv();
  1571. static enum xprt_stat    svctcp_stat();
  1572. static bool_t        svctcp_getargs();
  1573. static bool_t        svctcp_reply();
  1574. static bool_t        svctcp_freeargs();
  1575. static void        svctcp_destroy();
  1576.  
  1577. static struct xp_ops svctcp_op = {
  1578.     svctcp_recv,
  1579.     svctcp_stat,
  1580.     svctcp_getargs,
  1581.     svctcp_reply,
  1582.     svctcp_freeargs,
  1583.     svctcp_destroy
  1584. };
  1585.  
  1586. /*
  1587.  * Ops vector for TCP/IP rendezvous handler
  1588.  */
  1589. static bool_t        rendezvous_request();
  1590. static enum xprt_stat    rendezvous_stat();
  1591.  
  1592. static struct xp_ops svctcp_rendezvous_op = {
  1593.     rendezvous_request,
  1594.     rendezvous_stat,
  1595.     abort,
  1596.     abort,
  1597.     abort,
  1598.     svctcp_destroy
  1599. };
  1600.  
  1601. static int readtcp(), writetcp();
  1602.  
  1603. struct tcp_rendezvous { /* kept in xprt->xp_p1 */
  1604.     u_int sendsize;
  1605.     u_int recvsize;
  1606. };
  1607.  
  1608. struct tcp_conn {  /* kept in xprt->xp_p1 */
  1609.     enum xprt_stat strm_stat;
  1610.     u_long x_id;
  1611.     XDR xdrs;
  1612.     char verf_body[MAX_AUTH_BYTES];
  1613. };
  1614.  
  1615. /*
  1616.  * Usage:
  1617.  *    xprt = svctcp_create(sock, send_buf_size, recv_buf_size);
  1618.  *
  1619.  * Creates, registers, and returns a (rpc) tcp based transporter.
  1620.  * Once *xprt is initialized, it is registered as a transporter
  1621.  * see (svc.h, xprt_register).  This routine returns
  1622.  * a NULL if a problem occurred.
  1623.  *
  1624.  * If sock<0 then a socket is created, else sock is used.
  1625.  * If the socket, sock is not bound to a port then svctcp_create
  1626.  * binds it to an arbitrary port.  The routine then starts a tcp
  1627.  * listener on the socket's associated port.  In any (successful) case,
  1628.  * xprt->xp_sock is the registered socket number and xprt->xp_port is the
  1629.  * associated port number.
  1630.  *
  1631.  * Since tcp streams do buffered io similar to stdio, the caller can specify
  1632.  * how big the send and receive buffers are via the second and third parms;
  1633.  * 0 => use the system default.
  1634.  */
  1635. SVCXPRT *
  1636. svctcp_create(sock, sendsize, recvsize)
  1637.     register int sock;
  1638.     u_int sendsize;
  1639.     u_int recvsize;
  1640. {
  1641.     bool_t madesock = FALSE;
  1642.     register SVCXPRT *xprt;
  1643.     register struct tcp_rendezvous *r;
  1644.     struct sockaddr_in addr;
  1645.     int len = sizeof(struct sockaddr_in);
  1646.  
  1647.     if (sock == RPC_ANYSOCK) {
  1648.         if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
  1649.             perror("svctcp_.c - udp socket creation problem");
  1650.             return ((SVCXPRT *)NULL);
  1651.         }
  1652.         madesock = TRUE;
  1653.     }
  1654.     addr.sin_addr.s_addr = 0;
  1655.     addr.sin_family = AF_INET;
  1656.     addr.sin_port = 0;
  1657.     (void)bind(sock, (struct sockaddr *)&addr, len);
  1658.     if ((getsockname(sock, (caddr_t)&addr, &len) != 0)  ||
  1659.         (listen(sock, 2) != 0)) {
  1660.         perror("svctcp_.c - cannot getsockname or listen");
  1661.         if (madesock)
  1662.                (void)close(sock);
  1663.         return ((SVCXPRT *)NULL);
  1664.     }
  1665.     r = (struct tcp_rendezvous *)mem_alloc(sizeof(*r));
  1666.     if (r == NULL) {
  1667.         fprintf(stderr, "svctcp_create: out of memory\n");
  1668.         return (NULL);
  1669.     }
  1670.     r->sendsize = sendsize;
  1671.     r->recvsize = recvsize;
  1672.     xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT));
  1673.     if (xprt == NULL) {
  1674.         fprintf(stderr, "svctcp_create: out of memory\n");
  1675.         return (NULL);
  1676.     }
  1677.     xprt->xp_p2 = NULL;
  1678.     xprt->xp_p1 = (caddr_t)r;
  1679.     xprt->xp_verf = _null_auth;
  1680.     xprt->xp_ops = &svctcp_rendezvous_op;
  1681.     xprt->xp_port = ntohs(addr.sin_port);
  1682.     xprt->xp_sock = sock;
  1683.     xprt_register(xprt);
  1684.     return (xprt);
  1685. }
  1686.  
  1687. static bool_t
  1688. rendezvous_request(xprt)
  1689.     register SVCXPRT *xprt;
  1690. {
  1691.     register int sock;
  1692.     register struct tcp_rendezvous *r;
  1693.     register struct tcp_conn *cd;
  1694.     struct sockaddr_in addr;
  1695.     int len;
  1696.  
  1697.     r = (struct tcp_rendezvous *)xprt->xp_p1;
  1698.     again:
  1699.     len = sizeof(struct sockaddr_in);
  1700.     if ((sock = accept(xprt->xp_sock, (struct sockaddr *)&addr,
  1701.         &len)) < 0) {
  1702.         if (errno == EINTR)
  1703.             goto again;
  1704.            return (FALSE);
  1705.     }
  1706.     /*
  1707.      * make a new transporter (re-uses xprt)
  1708.      */
  1709.     xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT));
  1710.     if (xprt == NULL) {
  1711.         fprintf(stderr, "rendezvous_request: out of memory\n");
  1712.         return (FALSE);
  1713.     }
  1714.     cd = (struct tcp_conn *)mem_alloc(sizeof(struct tcp_conn));
  1715.     if (cd == NULL) {
  1716.         fprintf(stderr, "rendezvous_request: out of memory\n");
  1717.         return (FALSE);
  1718.     }
  1719.     cd->strm_stat = XPRT_IDLE;
  1720.     xdrrec_create(&(cd->xdrs), r->sendsize, r->recvsize,
  1721.         (caddr_t)xprt, readtcp, writetcp);
  1722.     xprt->xp_p2 = NULL;
  1723.     xprt->xp_p1 = (caddr_t)cd;
  1724.     xprt->xp_verf.oa_base = cd->verf_body;
  1725.     xprt->xp_raddr = addr;
  1726.     xprt->xp_addrlen = len;
  1727.     xprt->xp_ops = &svctcp_op;  /* truely deals with calls */
  1728.     xprt->xp_port = 0;  /* this is a connection, not a rendezvouser */
  1729.     xprt->xp_sock = sock;
  1730.     xprt_register(xprt);
  1731.     return (FALSE); /* there is never an rpc msg to be processed */
  1732. }
  1733.  
  1734. static enum xprt_stat
  1735. rendezvous_stat()
  1736. {
  1737.  
  1738.     return (XPRT_IDLE);
  1739. }
  1740.  
  1741. static void
  1742. svctcp_destroy(xprt)
  1743.     register SVCXPRT *xprt;
  1744. {
  1745.     register struct tcp_conn *cd = (struct tcp_conn *)xprt->xp_p1;
  1746.  
  1747.     xprt_unregister(xprt);
  1748.     (void)close(xprt->xp_sock);
  1749.     if (xprt->xp_port != 0) {
  1750.         /* a rendezvouser socket */
  1751.         xprt->xp_port = 0;
  1752.     } else {
  1753.         /* an actual connection socket */
  1754.         XDR_DESTROY(&(cd->xdrs));
  1755.     }
  1756.     mem_free((caddr_t)cd, sizeof(struct tcp_conn));
  1757.     mem_free((caddr_t)xprt, sizeof(SVCXPRT));
  1758. }
  1759.  
  1760. /*
  1761.  * All read operations timeout after 35 seconds.
  1762.  * A timeout is fatal for the connection.
  1763.  */
  1764. static struct timeval wait_per_try = { 35, 0 };
  1765.  
  1766. /*
  1767.  * reads data from the tcp conection.
  1768.  * any error is fatal and the connection is closed.
  1769.  * (And a read of zero bytes is a half closed stream => error.)
  1770.  */
  1771. static int
  1772. readtcp(xprt, buf, len)
  1773.     register SVCXPRT *xprt;
  1774.     caddr_t buf;
  1775.     register int len;
  1776. {
  1777.     register int sock = xprt->xp_sock;
  1778.     register int mask = 1 << sock;
  1779.     int readfds;
  1780.  
  1781.     do {
  1782.         readfds = mask;
  1783.         if (select(32, &readfds, NULL, NULL, &wait_per_try) <= 0) {
  1784.             if (errno == EINTR)
  1785.                 continue;
  1786.             goto fatal_err;
  1787.         }
  1788.     } while (readfds != mask);
  1789.     if ((len = read(sock, buf, len)) > 0)
  1790.         return (len);
  1791. fatal_err:
  1792.     ((struct tcp_conn *)(xprt->xp_p1))->strm_stat = XPRT_DIED;
  1793.     return (-1);
  1794. }
  1795.  
  1796. /*
  1797.  * writes data to the tcp connection.
  1798.  * Any error is fatal and the connection is closed.
  1799.  */
  1800. static int
  1801. writetcp(xprt, buf, len)
  1802.     register SVCXPRT *xprt;
  1803.     caddr_t buf;
  1804.     int len;
  1805. {
  1806.     register int i, cnt;
  1807.  
  1808.     for (cnt = len; cnt > 0; cnt -= i, buf += i) {
  1809.         if ((i = write(xprt->xp_sock, buf, cnt)) < 0) {
  1810.             ((struct tcp_conn *)(xprt->xp_p1))->strm_stat =
  1811.                 XPRT_DIED;
  1812.             return (-1);
  1813.         }
  1814.     }
  1815.     return (len);
  1816. }
  1817.  
  1818. static enum xprt_stat
  1819. svctcp_stat(xprt)
  1820.     SVCXPRT *xprt;
  1821. {
  1822.     register struct tcp_conn *cd =
  1823.         (struct tcp_conn *)(xprt->xp_p1);
  1824.  
  1825.     if (cd->strm_stat == XPRT_DIED)
  1826.         return (XPRT_DIED);
  1827.     if (! xdrrec_eof(&(cd->xdrs)))
  1828.         return (XPRT_MOREREQS);
  1829.     return (XPRT_IDLE);
  1830. }
  1831.  
  1832. static bool_t
  1833. svctcp_recv(xprt, msg)
  1834.     SVCXPRT *xprt;
  1835.     register struct rpc_msg *msg;
  1836. {
  1837.     register struct tcp_conn *cd =
  1838.         (struct tcp_conn *)(xprt->xp_p1);
  1839.     register XDR *xdrs = &(cd->xdrs);
  1840.  
  1841.     xdrs->x_op = XDR_DECODE;
  1842.     (void)xdrrec_skiprecord(xdrs);
  1843.     if (xdr_callmsg(xdrs, msg)) {
  1844.         cd->x_id = msg->rm_xid;
  1845.         return (TRUE);
  1846.     }
  1847.     return (FALSE);
  1848. }
  1849.  
  1850. static bool_t
  1851. svctcp_getargs(xprt, xdr_args, args_ptr)
  1852.     SVCXPRT *xprt;
  1853.     xdrproc_t xdr_args;
  1854.     caddr_t args_ptr;
  1855. {
  1856.  
  1857.     return ((*xdr_args)(&(((struct tcp_conn *)(xprt->xp_p1))->xdrs), args_ptr));
  1858. }
  1859.  
  1860. static bool_t
  1861. svctcp_freeargs(xprt, xdr_args, args_ptr)
  1862.     SVCXPRT *xprt;
  1863.     xdrproc_t xdr_args;
  1864.     caddr_t args_ptr;
  1865. {
  1866.     register XDR *xdrs =
  1867.         &(((struct tcp_conn *)(xprt->xp_p1))->xdrs);
  1868.  
  1869.     xdrs->x_op = XDR_FREE;
  1870.     return ((*xdr_args)(xdrs, args_ptr));
  1871. }
  1872.  
  1873. static bool_t
  1874. svctcp_reply(xprt, msg)
  1875.     SVCXPRT *xprt;
  1876.     register struct rpc_msg *msg;
  1877. {
  1878.     register struct tcp_conn *cd =
  1879.         (struct tcp_conn *)(xprt->xp_p1);
  1880.     register XDR *xdrs = &(cd->xdrs);
  1881.     register bool_t stat;
  1882.  
  1883.     xdrs->x_op = XDR_ENCODE;
  1884.     msg->rm_xid = cd->x_id;
  1885.     stat = xdr_replymsg(xdrs, msg);
  1886.     (void)xdrrec_endofrecord(xdrs, TRUE);
  1887.     return (stat);
  1888. }
  1889. !Funky!Stuff!
  1890. echo x - svc_udp.c
  1891. sed 's/^X//' >svc_udp.c <<'!Funky!Stuff!'
  1892. /*
  1893.  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  1894.  * unrestricted use provided that this legend is included on all tape
  1895.  * media and as a part of the software program in whole or part.  Users
  1896.  * may copy or modify Sun RPC without charge, but are not authorized
  1897.  * to license or distribute it to anyone else except as part of a product or
  1898.  * program developed by the user.
  1899.  * 
  1900.  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  1901.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  1902.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  1903.  * 
  1904.  * Sun RPC is provided with no support and without any obligation on the
  1905.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  1906.  * modification or enhancement.
  1907.  * 
  1908.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  1909.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  1910.  * OR ANY PART THEREOF.
  1911.  * 
  1912.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  1913.  * or profits or other special, indirect and consequential damages, even if
  1914.  * Sun has been advised of the possibility of such damages.
  1915.  * 
  1916.  * Sun Microsystems, Inc.
  1917.  * 2550 Garcia Avenue
  1918.  * Mountain View, California  94043
  1919.  */
  1920. #ifndef lint
  1921. static char sccsid[] = "@(#)svc_udp.c 1.4 85/03/14 Copyr 1984 Sun Micro";
  1922. #endif
  1923.  
  1924. /*
  1925.  * svc_udp.c,
  1926.  * Server side for UDP/IP based RPC.  (Does some caching in the hopes of
  1927.  * achieving execute-at-most-once semantics.)
  1928.  *
  1929.  * Copyright (C) 1984, Sun Microsystems, Inc.
  1930.  */
  1931.  
  1932. #include <stdio.h>
  1933. #include "types.h"
  1934. #include <netinet/in.h>
  1935. #include <sys/socket.h>
  1936. #include <errno.h>
  1937. #include "xdr.h"
  1938. #include "auth.h"
  1939. #include "clnt.h"
  1940. #include "rpc_msg.h"
  1941. #include "svc.h"
  1942.  
  1943. char *mem_alloc();
  1944.  
  1945. #define rpc_buffer(xprt) ((xprt)->xp_p1)
  1946.  
  1947. static bool_t        svcudp_recv();
  1948. static bool_t        svcudp_reply();
  1949. static enum xprt_stat    svcudp_stat();
  1950. static bool_t        svcudp_getargs();
  1951. static bool_t        svcudp_freeargs();
  1952. static void        svcudp_destroy();
  1953.  
  1954. static struct xp_ops svcudp_op = {
  1955.     svcudp_recv,
  1956.     svcudp_stat,
  1957.     svcudp_getargs,
  1958.     svcudp_reply,
  1959.     svcudp_freeargs,
  1960.     svcudp_destroy
  1961. };
  1962.  
  1963. extern int errno;
  1964.  
  1965. /*
  1966.  * kept in xprt->xp_p2
  1967.  */
  1968. struct svcudp_data {
  1969.     u_long    su_xid;        /* transaction id */
  1970.     XDR    su_xdrs;    /* XDR handle */
  1971.     char    su_verfbody[MAX_AUTH_BYTES];    /* verifier body */
  1972. };
  1973. #define    su_data(xprt)    ((struct svcudp_data *)(xprt->xp_p2))
  1974.  
  1975. /*
  1976.  * Usage:
  1977.  *    xprt = svcudp_create(sock);
  1978.  *
  1979.  * If sock<0 then a socket is created, else sock is used.
  1980.  * If the socket, sock is not bound to a port then svcudp_create
  1981.  * binds it to an arbitrary port.  In any (successful) case,
  1982.  * xprt->xp_sock is the registered socket number and xprt->xp_port is the
  1983.  * associated port number.
  1984.  * Once *xprt is initialized, it is registered as a transporter;
  1985.  * see (svc.h, xprt_register).
  1986.  * The routines returns NULL if a problem occurred.
  1987.  */
  1988. SVCXPRT *
  1989. svcudp_create(sock)
  1990.     register int sock;
  1991. {
  1992.     bool_t madesock = FALSE;
  1993.     register SVCXPRT *xprt;
  1994.     register struct svcudp_data *su;
  1995.     struct sockaddr_in addr;
  1996.     int len = sizeof(struct sockaddr_in);
  1997.  
  1998.     if (sock == RPC_ANYSOCK) {
  1999.         if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
  2000.             perror("svcudp_create: socket creation problem");
  2001.             return ((SVCXPRT *)NULL);
  2002.         }
  2003.         madesock = TRUE;
  2004.     }
  2005.     addr.sin_addr.s_addr = 0;
  2006.     addr.sin_family = AF_INET;
  2007.     addr.sin_port = 0;
  2008.     (void)bind(sock, (struct sockaddr *)&addr, len);
  2009.     if (getsockname(sock, (caddr_t)&addr, &len) != 0) {
  2010.         perror("svcudp_create - cannot getsockname");
  2011.         if (madesock)
  2012.             (void)close(sock);
  2013.         return ((SVCXPRT *)NULL);
  2014.     }
  2015.     xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT));
  2016.     if (xprt == NULL) {
  2017.         fprintf(stderr, "svcudp_create: out of memory\n");
  2018.         return (NULL);
  2019.     }
  2020.     if ((rpc_buffer(xprt) = mem_alloc(UDPMSGSIZE)) == NULL) {
  2021.         fprintf(stderr, "svcudp_create: out of memory\n");
  2022.         return (NULL);
  2023.     }
  2024.     su = (struct svcudp_data *)mem_alloc(sizeof(*su));
  2025.     if (su == NULL) {
  2026.         fprintf(stderr, "svcudp_create: out of memory\n");
  2027.         return (NULL);
  2028.     }
  2029.     xdrmem_create(
  2030.         &(su->su_xdrs), rpc_buffer(xprt), UDPMSGSIZE, XDR_DECODE);
  2031.     xprt->xp_p2 = (caddr_t)su;
  2032.     xprt->xp_verf.oa_base = su->su_verfbody;
  2033.     xprt->xp_ops = &svcudp_op;
  2034.     xprt->xp_port = ntohs(addr.sin_port);
  2035.     xprt->xp_sock = sock;
  2036.     xprt_register(xprt);
  2037.     return (xprt);
  2038. }
  2039.  
  2040. static enum xprt_stat
  2041. svcudp_stat(xprt)
  2042.     SVCXPRT *xprt;
  2043. {
  2044.  
  2045.     return (XPRT_IDLE); 
  2046. }
  2047.  
  2048. static bool_t
  2049. svcudp_recv(xprt, msg)
  2050.     register SVCXPRT *xprt;
  2051.     struct rpc_msg *msg;
  2052. {
  2053.     register struct svcudp_data *su = su_data(xprt);
  2054.     register XDR *xdrs = &(su->su_xdrs);
  2055.     register int rlen;
  2056.  
  2057.     again:
  2058.     xprt->xp_addrlen = sizeof(struct sockaddr_in);
  2059.     rlen = recvfrom(xprt->xp_sock, rpc_buffer(xprt), UDPMSGSIZE,
  2060.         0, (struct sockaddr *)&(xprt->xp_raddr), &(xprt->xp_addrlen));
  2061.     if (rlen == -1 && errno == EINTR)
  2062.         goto again;
  2063.     if (rlen < 4*sizeof(u_long))
  2064.         return (FALSE);
  2065.     xdrs->x_op = XDR_DECODE;
  2066.     XDR_SETPOS(xdrs, 0);
  2067.     if (! xdr_callmsg(xdrs, msg))
  2068.         return (FALSE);
  2069.     su->su_xid = msg->rm_xid;
  2070.     return (TRUE);
  2071. }
  2072.  
  2073. static bool_t
  2074. svcudp_reply(xprt, msg)
  2075.     register SVCXPRT *xprt; 
  2076.     struct rpc_msg *msg; 
  2077. {
  2078.     register struct svcudp_data *su = su_data(xprt);
  2079.     register XDR *xdrs = &(su->su_xdrs);
  2080.     register int slen;
  2081.     register bool_t stat = FALSE;
  2082.  
  2083.     xdrs->x_op = XDR_ENCODE;
  2084.     XDR_SETPOS(xdrs, 0);
  2085.     msg->rm_xid = su->su_xid;
  2086.     if (xdr_replymsg(xdrs, msg)) {
  2087.         slen = (int)XDR_GETPOS(xdrs);
  2088.         if (sendto(xprt->xp_sock, rpc_buffer(xprt), slen, 0,
  2089.             (struct sockaddr *)&(xprt->xp_raddr), xprt->xp_addrlen)
  2090.             == slen)
  2091.             stat = TRUE;
  2092.     }
  2093.     return (stat);
  2094. }
  2095.  
  2096. static bool_t
  2097. svcudp_getargs(xprt, xdr_args, args_ptr)
  2098.     SVCXPRT *xprt;
  2099.     xdrproc_t xdr_args;
  2100.     caddr_t args_ptr;
  2101. {
  2102.  
  2103.     return ((*xdr_args)(&(su_data(xprt)->su_xdrs), args_ptr));
  2104. }
  2105.  
  2106. static bool_t
  2107. svcudp_freeargs(xprt, xdr_args, args_ptr)
  2108.     SVCXPRT *xprt;
  2109.     xdrproc_t xdr_args;
  2110.     caddr_t args_ptr;
  2111. {
  2112.     register XDR *xdrs = &(su_data(xprt)->su_xdrs);
  2113.  
  2114.     xdrs->x_op = XDR_FREE;
  2115.     return ((*xdr_args)(xdrs, args_ptr));
  2116. }
  2117.  
  2118. static void
  2119. svcudp_destroy(xprt)
  2120.     register SVCXPRT *xprt;
  2121. {
  2122.     register struct svcudp_data *su = su_data(xprt);
  2123.  
  2124.     xprt_unregister(xprt);
  2125.     (void)close(xprt->xp_sock);
  2126.     XDR_DESTROY(&(su->su_xdrs));
  2127.     mem_free((caddr_t)su, sizeof(struct svcudp_data));
  2128.     mem_free(rpc_buffer(xprt), UDPMSGSIZE);
  2129.     mem_free((caddr_t)xprt, sizeof(SVCXPRT));
  2130. }
  2131. !Funky!Stuff!
  2132.  
  2133. exit
  2134.