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

  1. Date: Wed, 3 Apr 85 00:05:44 pst
  2. From: decvax!sun!pumpkinseed!blyon (Bob Lyon)
  3. Subject: Sun RPC part 7 of 10
  4.  
  5. echo x - auth.h
  6. sed 's/^X//' >auth.h <<'!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. /*      @(#)auth.h 1.3 85/03/28 SMI      */
  36.  
  37. /*
  38.  * auth.h, Authentication interface.
  39.  
  40.  * Copyright (C) 1984, Sun Microsystems, Inc.
  41.  *
  42.  * The data structures are completely opaque to the client.  The client
  43.  * is required to pass a AUTH * to routines that create rpc
  44.  * "sessions".
  45.  */
  46.  
  47.  
  48. #define MAX_AUTH_BYTES    400
  49.  
  50.  
  51. /*
  52.  * Status returned from authentication check
  53.  */
  54. enum auth_stat {
  55.     AUTH_OK=0,
  56.     /*
  57.      * failed at remote end
  58.      */
  59.     AUTH_BADCRED=1,            /* bogus credentials (seal broken) */
  60.     AUTH_REJECTEDCRED=2,        /* client should begin new session */
  61.     AUTH_BADVERF=3,            /* bogus verifier (seal broken) */
  62.     AUTH_REJECTEDVERF=4,        /* verifier expired or was replayed */
  63.     AUTH_TOOWEAK=5,            /* rejected due to security reasons */
  64.     /*
  65.      * failed locally
  66.     */
  67.     AUTH_INVALIDRESP=6,        /* bogus response verifier */
  68.     AUTH_FAILED=7            /* some unknown reason */
  69. };
  70.  
  71.  
  72. union des_block {
  73.     struct {
  74.         u_long high;
  75.         u_long low;
  76.     } key;
  77.     char c[8];
  78. };
  79.  
  80.  
  81. /*
  82.  * Authentication info.  Opaque to client.
  83.  */
  84. struct opaque_auth {
  85.     enum_t    oa_flavor;        /* flavor of auth */
  86.     caddr_t    oa_base;        /* address of more auth stuff */
  87.     u_int    oa_length;        /* not to exceed MAX_AUTH_BYTES */
  88. };
  89.  
  90.  
  91. /*
  92.  * Auth handle, interface to client side authenticators.
  93.  */
  94. typedef struct {
  95.     struct    opaque_auth    ah_cred;
  96.     struct    opaque_auth    ah_verf;
  97.     union    des_block    ah_key;
  98.     struct auth_ops {
  99.         void    (*ah_nextverf)();
  100.         int    (*ah_marshal)();    /* nextverf & serialize */
  101.         int    (*ah_validate)();    /* validate varifier */
  102.         int    (*ah_refresh)();    /* refresh credentials */
  103.         void    (*ah_destroy)();    /* destroy this structure */
  104.     } *ah_ops;
  105.     caddr_t ah_private;
  106. } AUTH;
  107.  
  108.  
  109. /*
  110.  * Authentication ops.
  111.  * The ops and the auth handle provide the interface to the authenticators.
  112.  *
  113.  * AUTH    *auth;
  114.  * XDR    *xdrs;
  115.  * struct opaque_auth verf;
  116.  */
  117. #define AUTH_NEXTVERF(auth)        \
  118.         ((*((auth)->ah_ops->ah_nextverf))(auth))
  119. #define auth_nextverf(auth)        \
  120.         ((*((auth)->ah_ops->ah_nextverf))(auth))
  121.  
  122. #define AUTH_MARSHALL(auth, xdrs)    \
  123.         ((*((auth)->ah_ops->ah_marshal))(auth, xdrs))
  124. #define auth_marshall(auth, xdrs)    \
  125.         ((*((auth)->ah_ops->ah_marshal))(auth, xdrs))
  126.  
  127. #define AUTH_VALIDATE(auth, verfp)    \
  128.         ((*((auth)->ah_ops->ah_validate))((auth), verfp))
  129. #define auth_validate(auth, verfp)    \
  130.         ((*((auth)->ah_ops->ah_validate))((auth), verfp))
  131.  
  132. #define AUTH_REFRESH(auth)    \
  133.         ((*((auth)->ah_ops->ah_refresh))(auth))
  134. #define auth_refresh(auth)    \
  135.         ((*((auth)->ah_ops->ah_refresh))(auth))
  136.  
  137. #define AUTH_DESTROY(auth)        \
  138.         ((*((auth)->ah_ops->ah_destroy))(auth))
  139. #define auth_destroy(auth)        \
  140.         ((*((auth)->ah_ops->ah_destroy))(auth))
  141.  
  142.  
  143. extern struct opaque_auth _null_auth;
  144.  
  145.  
  146. /*
  147.  * These are the various implementations of client side authenticators.
  148.  */
  149.  
  150. /*
  151.  * Null authentication
  152.  */
  153. extern AUTH *authnone_create();        /* takes no parameters */
  154. #define    AUTH_NULL    0
  155.  
  156. /*
  157.  * Unix style authentication
  158.  * AUTH *authunix_create(machname, uid, gid, len, aup_gids)
  159.  *    char *machname;
  160.  *    int uid;
  161.  *    int gid;
  162.  *    int len;
  163.  *    int *aup_gids;
  164.  */
  165. extern AUTH *authunix_create();
  166. extern AUTH *authunix_create_default();    /* takes no parameters */
  167. #define    AUTH_UNIX    1        /* unix style (uid, gids) */
  168. #define    AUTH_SHORT    2        /* short hand unix style */
  169.  
  170. !Funky!Stuff!
  171. echo x - auth_none.c
  172. sed 's/^X//' >auth_none.c <<'!Funky!Stuff!'
  173. /*
  174.  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  175.  * unrestricted use provided that this legend is included on all tape
  176.  * media and as a part of the software program in whole or part.  Users
  177.  * may copy or modify Sun RPC without charge, but are not authorized
  178.  * to license or distribute it to anyone else except as part of a product or
  179.  * program developed by the user.
  180.  * 
  181.  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  182.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  183.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  184.  * 
  185.  * Sun RPC is provided with no support and without any obligation on the
  186.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  187.  * modification or enhancement.
  188.  * 
  189.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  190.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  191.  * OR ANY PART THEREOF.
  192.  * 
  193.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  194.  * or profits or other special, indirect and consequential damages, even if
  195.  * Sun has been advised of the possibility of such damages.
  196.  * 
  197.  * Sun Microsystems, Inc.
  198.  * 2550 Garcia Avenue
  199.  * Mountain View, California  94043
  200.  */
  201. #ifndef lint
  202. static char sccsid[] = "@(#)auth_none.c 1.4 85/03/17 Copyr 1984 Sun Micro";
  203. #endif
  204.  
  205. /*
  206.  * auth_none.c
  207.  * Creates a client authentication handle for passing "null" 
  208.  * credentials and verifiers to remote systems. 
  209.  * 
  210.  * Copyright (C) 1984, Sun Microsystems, Inc. 
  211.  */
  212.  
  213. #include "types.h"
  214. #include "xdr.h"
  215. #include "auth.h"
  216. #define NULL ((caddr_t)0)
  217. #define MAX_MARSHEL_SIZE 20
  218.  
  219. /*
  220.  * Authenticator operations routines
  221.  */
  222. static void    authnone_verf();
  223. static void    authnone_destroy();
  224. static bool_t    authnone_marshal();
  225. static bool_t    authnone_validate();
  226. static bool_t    authnone_refresh();
  227.  
  228. static struct auth_ops ops = {
  229.     authnone_verf,
  230.     authnone_marshal,
  231.     authnone_validate,
  232.     authnone_refresh,
  233.     authnone_destroy
  234. };
  235.  
  236. static AUTH    no_client;
  237. static char    marshalled_client[MAX_MARSHEL_SIZE];
  238. static u_int    mcnt = 0;
  239.  
  240. AUTH *
  241. authnone_create()
  242. {
  243.     XDR xdr_stream;
  244.     register XDR *xdrs;
  245.  
  246.     if (! mcnt) {
  247.         no_client.ah_cred = no_client.ah_verf = _null_auth;
  248.         no_client.ah_ops = &ops;
  249.         xdrs = &xdr_stream;
  250.         xdrmem_create(xdrs, marshalled_client, (u_int)MAX_MARSHEL_SIZE,
  251.             XDR_ENCODE);
  252.         if ((! xdr_opaque_auth(xdrs, &no_client.ah_cred)) ||
  253.             (! xdr_opaque_auth(xdrs, &no_client.ah_verf))) {
  254.         } else {
  255.             mcnt = XDR_GETPOS(xdrs);
  256.         }
  257.         XDR_DESTROY(xdrs);
  258.     }
  259.     return (&no_client);
  260. }
  261.  
  262. static bool_t
  263. /* ARGSUSED */
  264. authnone_marshal(client, xdrs)
  265.     AUTH *client;
  266.     XDR *xdrs;
  267. {
  268.  
  269.     return ((*xdrs->x_ops->x_putbytes)(xdrs, marshalled_client, mcnt));
  270. }
  271.  
  272. static void 
  273. authnone_verf()
  274. {
  275. }
  276.  
  277. static bool_t
  278. authnone_validate()
  279. {
  280.  
  281.     return (TRUE);
  282. }
  283.  
  284. static bool_t
  285. authnone_refresh()
  286. {
  287.  
  288.     return (FALSE);
  289. }
  290.  
  291. static void
  292. authnone_destroy()
  293. {
  294. }
  295. !Funky!Stuff!
  296. echo x - auth_unix.c
  297. sed 's/^X//' >auth_unix.c <<'!Funky!Stuff!'
  298. /*
  299.  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  300.  * unrestricted use provided that this legend is included on all tape
  301.  * media and as a part of the software program in whole or part.  Users
  302.  * may copy or modify Sun RPC without charge, but are not authorized
  303.  * to license or distribute it to anyone else except as part of a product or
  304.  * program developed by the user.
  305.  * 
  306.  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  307.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  308.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  309.  * 
  310.  * Sun RPC is provided with no support and without any obligation on the
  311.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  312.  * modification or enhancement.
  313.  * 
  314.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  315.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  316.  * OR ANY PART THEREOF.
  317.  * 
  318.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  319.  * or profits or other special, indirect and consequential damages, even if
  320.  * Sun has been advised of the possibility of such damages.
  321.  * 
  322.  * Sun Microsystems, Inc.
  323.  * 2550 Garcia Avenue
  324.  * Mountain View, California  94043
  325.  */
  326. #ifndef lint
  327. static char sccsid[] = "@(#)auth_unix.c 1.5 85/03/17 Copyr 1984 Sun Micro";
  328. #endif
  329.  
  330. /*
  331.  * auth_unix.c, Implements UNIX style authentication parameters. 
  332.  *  
  333.  * Copyright (C) 1984, Sun Microsystems, Inc. 
  334.  *
  335.  * The system is very weak.  The client uses no encryption for it's
  336.  * credentials and only sends null verifiers.  The server sends backs
  337.  * null verifiers or optionally a verifier that suggests a new short hand
  338.  * for the credentials.
  339.  *
  340.  */
  341.  
  342. #include <stdio.h>
  343. #include "types.h"
  344. #include <sys/time.h>
  345. #include "xdr.h"
  346. #include "auth.h"
  347. #include "auth_unix.h"
  348. char *malloc();
  349.  
  350. /*
  351.  * Unix authenticator operations vector
  352.  */
  353. static void    authunix_nextverf();
  354. static bool_t    authunix_marshal();
  355. static bool_t    authunix_validate();
  356. static bool_t    authunix_refresh();
  357. static void    authunix_destroy();
  358.  
  359. static struct auth_ops auth_unix_ops = {
  360.     authunix_nextverf,
  361.     authunix_marshal,
  362.     authunix_validate,
  363.     authunix_refresh,
  364.     authunix_destroy
  365. };
  366.  
  367. /*
  368.  * This struct is pointed to by the ah_private field of an auth_handle.
  369.  */
  370. struct audata {
  371.     struct opaque_auth    au_origcred;    /* original credentials */
  372.     struct opaque_auth    au_shcred;    /* short hand cred */
  373.     u_long            au_shfaults;    /* short hand cache faults */
  374.     char            au_marshed[MAX_AUTH_BYTES];
  375.     u_int            au_mpos;    /* xdr pos at end of marshed */
  376. };
  377. #define    AUTH_PRIVATE(auth)    ((struct audata *)auth->ah_private)
  378.  
  379. static bool_t marshal_new_auth();
  380.  
  381.  
  382. /*
  383.  * Create a unix style authenticator.
  384.  * Returns an auth handle with the given stuff in it.
  385.  */
  386. AUTH *
  387. authunix_create(machname, uid, gid, len, aup_gids)
  388.     char *machname;
  389.     int uid;
  390.     int gid;
  391.     register int len;
  392.     int *aup_gids;
  393. {
  394.     struct authunix_parms aup;
  395.     char mymem[MAX_AUTH_BYTES];
  396.     struct timeval now;
  397.     XDR xdrs;
  398.     register AUTH *auth;
  399.     register struct audata *au;
  400.  
  401.     /*
  402.      * Allocate and set up auth handle
  403.      */
  404.     auth = (AUTH *)mem_alloc(sizeof(*auth));
  405.     if (auth == NULL) {
  406.         fprintf(stderr, "authunix_create: out of memory\n");
  407.         return (NULL);
  408.     }
  409.     au = (struct audata *)mem_alloc(sizeof(*au));
  410.     if (au == NULL) {
  411.         fprintf(stderr, "authunix_create: out of memory\n");
  412.         return (NULL);
  413.     }
  414.     auth->ah_ops = &auth_unix_ops;
  415.     auth->ah_private = (caddr_t)au;
  416.     auth->ah_verf = au->au_shcred = _null_auth;
  417.     au->au_shfaults = 0;
  418.  
  419.     /*
  420.      * fill in param struct from the given params
  421.      */
  422.     (void)gettimeofday(&now,  (struct timezone *)0);
  423.     aup.aup_time = now.tv_sec;
  424.     aup.aup_machname = machname;
  425.     aup.aup_uid = uid;
  426.     aup.aup_gid = gid;
  427.     aup.aup_len = (u_int)len;
  428.     aup.aup_gids = aup_gids;
  429.  
  430.     /*
  431.      * Serialize the parameters into origcred
  432.      */
  433.     xdrmem_create(&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE);
  434.     if (! xdr_authunix_parms(&xdrs, &aup)) 
  435.         abort();
  436.     au->au_origcred.oa_length = len = XDR_GETPOS(&xdrs);
  437.     au->au_origcred.oa_flavor = AUTH_UNIX;
  438.     if ((au->au_origcred.oa_base = mem_alloc(len)) == NULL) {
  439.         fprintf(stderr, "authunix_create: out of memory\n");
  440.         return (NULL);
  441.     }
  442.     bcopy(mymem, au->au_origcred.oa_base, (u_int)len);
  443.  
  444.     /*
  445.      * set auth handle to reflect new cred.
  446.      */
  447.     auth->ah_cred = au->au_origcred;
  448.     marshal_new_auth(auth);
  449.     return (auth);
  450. }
  451.  
  452. /*
  453.  * Returns an auth handle with parameters determined by doing lots of
  454.  * syscalls.
  455.  */
  456. AUTH *
  457. authunix_create_default()
  458. {
  459.     register int len;
  460.     char machname[MAX_MACHINE_NAME + 1];
  461.     register int uid;
  462.     register int gid;
  463.     int gids[NGRPS];
  464.  
  465.     if (gethostname(machname, MAX_MACHINE_NAME) == -1)
  466.         abort();
  467.     machname[MAX_MACHINE_NAME] = 0;
  468.     uid = geteuid();
  469.     gid = getegid();
  470.     if ((len = getgroups(NGRPS, gids)) < 0)
  471.         abort();
  472.     return (authunix_create(machname, uid, gid, len, gids));
  473. }
  474.  
  475. /*
  476.  * authunix operations
  477.  */
  478.  
  479. static void
  480. authunix_nextverf(auth)
  481.     AUTH *auth;
  482. {
  483.     /* no action necessary */
  484. }
  485.  
  486. static bool_t
  487. authunix_marshal(auth, xdrs)
  488.     AUTH *auth;
  489.     XDR *xdrs;
  490. {
  491.     register struct audata *au = AUTH_PRIVATE(auth);
  492.  
  493.     return (XDR_PUTBYTES(xdrs, au->au_marshed, au->au_mpos));
  494. }
  495.  
  496. static bool_t
  497. authunix_validate(auth, verf)
  498.     register AUTH *auth;
  499.     struct opaque_auth verf;
  500. {
  501.     register struct audata *au;
  502.     XDR xdrs;
  503.  
  504.     if (verf.oa_flavor == AUTH_SHORT) {
  505.         au = AUTH_PRIVATE(auth);
  506.         xdrmem_create(&xdrs, verf.oa_base, verf.oa_length, XDR_DECODE);
  507.  
  508.         if (au->au_shcred.oa_base != NULL) {
  509.             mem_free(au->au_shcred.oa_base, au->au_shcred.oa_length);
  510.             au->au_shcred.oa_base = NULL;
  511.         }
  512.         if (xdr_opaque_auth(&xdrs, &au->au_shcred)) {
  513.             auth->ah_cred = au->au_shcred;
  514.         } else {
  515.             xdrs.x_op = XDR_FREE;
  516.             (void)xdr_opaque_auth(&xdrs, &au->au_shcred);
  517.             au->au_shcred.oa_base = NULL;
  518.             auth->ah_cred = au->au_origcred;
  519.         }
  520.         marshal_new_auth(auth);
  521.     }
  522.     return (TRUE);
  523. }
  524.  
  525. static bool_t
  526. authunix_refresh(auth)
  527.     register AUTH *auth;
  528. {
  529.     register struct audata *au = AUTH_PRIVATE(auth);
  530.     struct authunix_parms aup;
  531.     struct timeval now;
  532.     XDR xdrs;
  533.     register int stat;
  534.  
  535.     if (auth->ah_cred.oa_base == au->au_origcred.oa_base) {
  536.         /* there is no hope.  Punt */
  537.         return (FALSE);
  538.     }
  539.     au->au_shfaults ++;
  540.  
  541.     /* first deserialize the creds back into a struct authunix_parms */
  542.     aup.aup_machname = NULL;
  543.     aup.aup_gids = (int *)NULL;
  544.     xdrmem_create(&xdrs, au->au_origcred.oa_base,
  545.         au->au_origcred.oa_length, XDR_DECODE);
  546.     stat = xdr_authunix_parms(&xdrs, &aup);
  547.     if (! stat) 
  548.         goto done;
  549.  
  550.     /* update the time and serialize in place */
  551.     (void)gettimeofday(&now, (struct timezone *)0);
  552.     aup.aup_time = now.tv_sec;
  553.     xdrs.x_op = XDR_ENCODE;
  554.     XDR_SETPOS(&xdrs, 0);
  555.     stat = xdr_authunix_parms(&xdrs, &aup);
  556.     if (! stat)
  557.         goto done;
  558.     auth->ah_cred = au->au_origcred;
  559.     marshal_new_auth(auth);
  560. done:
  561.     /* free the struct authunix_parms created by deserializing */
  562.     xdrs.x_op = XDR_FREE;
  563.     (void)xdr_authunix_parms(&xdrs, &aup);
  564.     XDR_DESTROY(&xdrs);
  565.     return (stat);
  566. }
  567.  
  568. static void
  569. authunix_destroy(auth)
  570.     register AUTH *auth;
  571. {
  572.     register struct audata *au = AUTH_PRIVATE(auth);
  573.  
  574.     mem_free(au->au_origcred.oa_base, au->au_origcred.oa_length);
  575.  
  576.     if (au->au_shcred.oa_base != NULL)
  577.         mem_free(au->au_shcred.oa_base, au->au_shcred.oa_length);
  578.  
  579.     mem_free(auth->ah_private, sizeof(struct audata));
  580.  
  581.     if (auth->ah_verf.oa_base != NULL)
  582.         mem_free(auth->ah_verf.oa_base, auth->ah_verf.oa_length);
  583.  
  584.     mem_free((caddr_t)auth, sizeof(*auth));
  585.  
  586. }
  587.  
  588. /*
  589.  * Marshals (pre-serializes) an auth struct.
  590.  * sets private data, au_marshed and au_mpos
  591.  */
  592. static bool_t
  593. marshal_new_auth(auth)
  594.     register AUTH *auth;
  595. {
  596.     XDR        xdr_stream;
  597.     register XDR    *xdrs = &xdr_stream;
  598.     register struct audata *au = AUTH_PRIVATE(auth);
  599.  
  600.     xdrmem_create(xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE);
  601.     if ((! xdr_opaque_auth(xdrs, &(auth->ah_cred))) ||
  602.         (! xdr_opaque_auth(xdrs, &(auth->ah_verf)))) {
  603.     } else {
  604.         au->au_mpos = XDR_GETPOS(xdrs);
  605.     }
  606.     XDR_DESTROY(xdrs);
  607. }
  608. !Funky!Stuff!
  609. echo x - auth_unix.h
  610. sed 's/^X//' >auth_unix.h <<'!Funky!Stuff!'
  611. /*
  612.  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  613.  * unrestricted use provided that this legend is included on all tape
  614.  * media and as a part of the software program in whole or part.  Users
  615.  * may copy or modify Sun RPC without charge, but are not authorized
  616.  * to license or distribute it to anyone else except as part of a product or
  617.  * program developed by the user.
  618.  * 
  619.  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  620.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  621.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  622.  * 
  623.  * Sun RPC is provided with no support and without any obligation on the
  624.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  625.  * modification or enhancement.
  626.  * 
  627.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  628.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  629.  * OR ANY PART THEREOF.
  630.  * 
  631.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  632.  * or profits or other special, indirect and consequential damages, even if
  633.  * Sun has been advised of the possibility of such damages.
  634.  * 
  635.  * Sun Microsystems, Inc.
  636.  * 2550 Garcia Avenue
  637.  * Mountain View, California  94043
  638.  */
  639. /*      @(#)auth_unix.h 1.1 84/12/20 SMI      */
  640.  
  641. /*
  642.  * auth_unix.h, Protocol for UNIX style authentication parameters for RPC
  643.  *
  644.  * Copyright (C) 1984, Sun Microsystems, Inc.
  645.  */
  646.  
  647. /*
  648.  * The system is very weak.  The client uses no encryption for  it
  649.  * credentials and only sends null verifiers.  The server sends backs
  650.  * null verifiers or optionally a verifier that suggests a new short hand
  651.  * for the credentials.
  652.  */
  653.  
  654. /* The machine name is part of a credential; it may not exceed 255 bytes */
  655. #define MAX_MACHINE_NAME 255
  656.  
  657. /* gids compose part of a credential; there may not be more than 10 of them */
  658. #define NGRPS 8
  659.  
  660. /*
  661.  * Unix style credentials.
  662.  */
  663. struct authunix_parms {
  664.     u_long     aup_time;
  665.     char    *aup_machname;
  666.     int     aup_uid;
  667.     int     aup_gid;
  668.     u_int     aup_len;
  669.     int    *aup_gids;
  670. };
  671.  
  672. extern bool_t xdr_authunix_parms();
  673.  
  674. /* 
  675.  * If a response verifier has flavor AUTH_SHORT, 
  676.  * then the body of the response verifier encapsulates the following structure;
  677.  * again it is serialized in the obvious fashion.
  678.  */
  679. struct short_hand_verf {
  680.     struct opaque_auth new_cred;
  681. };
  682. !Funky!Stuff!
  683. echo x - authunix_prot.c
  684. sed 's/^X//' >authunix_prot.c <<'!Funky!Stuff!'
  685. /*
  686.  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  687.  * unrestricted use provided that this legend is included on all tape
  688.  * media and as a part of the software program in whole or part.  Users
  689.  * may copy or modify Sun RPC without charge, but are not authorized
  690.  * to license or distribute it to anyone else except as part of a product or
  691.  * program developed by the user.
  692.  * 
  693.  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  694.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  695.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  696.  * 
  697.  * Sun RPC is provided with no support and without any obligation on the
  698.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  699.  * modification or enhancement.
  700.  * 
  701.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  702.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  703.  * OR ANY PART THEREOF.
  704.  * 
  705.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  706.  * or profits or other special, indirect and consequential damages, even if
  707.  * Sun has been advised of the possibility of such damages.
  708.  * 
  709.  * Sun Microsystems, Inc.
  710.  * 2550 Garcia Avenue
  711.  * Mountain View, California  94043
  712.  */
  713. #ifndef lint
  714. static char sccsid[] = "@(#)authunix_prot.c 1.3 85/03/12 Copyr 1984 Sun Micro";
  715. #endif
  716.  
  717. /*
  718.  * authunix_prot.c
  719.  * XDR for UNIX style authentication parameters for RPC
  720.  *
  721.  * Copyright (C) 1984, Sun Microsystems, Inc.
  722.  */
  723.  
  724. #include "types.h"
  725. #include "xdr.h"
  726. #include "auth.h"
  727. #include "auth_unix.h"
  728.  
  729. /*
  730.  * XDR for unix authentication parameters.
  731.  */
  732. bool_t
  733. xdr_authunix_parms(xdrs, p)
  734.     register XDR *xdrs;
  735.     register struct authunix_parms *p;
  736. {
  737.     int i;
  738.  
  739.     if (xdr_u_long(xdrs, &(p->aup_time))
  740.         && xdr_string(xdrs, &(p->aup_machname), MAX_MACHINE_NAME)
  741.         && xdr_int(xdrs, &(p->aup_uid))
  742.         && xdr_int(xdrs, &(p->aup_gid))
  743.         && xdr_array(xdrs, (caddr_t *)&(p->aup_gids),
  744.             &(p->aup_len), NGRPS, sizeof(int), xdr_int) ) {
  745.         return (TRUE);
  746.     }
  747.     return (FALSE);
  748. }
  749.  
  750. !Funky!Stuff!
  751. echo x - clnt.h
  752. sed 's/^X//' >clnt.h <<'!Funky!Stuff!'
  753. /*
  754.  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  755.  * unrestricted use provided that this legend is included on all tape
  756.  * media and as a part of the software program in whole or part.  Users
  757.  * may copy or modify Sun RPC without charge, but are not authorized
  758.  * to license or distribute it to anyone else except as part of a product or
  759.  * program developed by the user.
  760.  * 
  761.  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  762.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  763.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  764.  * 
  765.  * Sun RPC is provided with no support and without any obligation on the
  766.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  767.  * modification or enhancement.
  768.  * 
  769.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  770.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  771.  * OR ANY PART THEREOF.
  772.  * 
  773.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  774.  * or profits or other special, indirect and consequential damages, even if
  775.  * Sun has been advised of the possibility of such damages.
  776.  * 
  777.  * Sun Microsystems, Inc.
  778.  * 2550 Garcia Avenue
  779.  * Mountain View, California  94043
  780.  */
  781. /*      @(#)clnt.h 1.3 85/03/20 SMI      */
  782.  
  783. /*
  784.  * clnt.h - Client side remote procedure call interface.
  785.  *
  786.  * Copyright (C) 1984, Sun Microsystems, Inc.
  787.  */
  788.  
  789. /*
  790.  * Rpc calls return an enum clnt_stat.  This should be looked at more,
  791.  * since each implementation is required to live with this (implementation
  792.  * independent) list of errors.
  793.  */
  794. enum clnt_stat {
  795.     RPC_SUCCESS=0,            /* call succeeded */
  796.     /*
  797.      * local errors
  798.      */
  799.     RPC_CANTENCODEARGS=1,        /* can't encode arguments */
  800.     RPC_CANTDECODERES=2,        /* can't decode results */
  801.     RPC_CANTSEND=3,            /* failure in sending call */
  802.     RPC_CANTRECV=4,            /* failure in receiving result */
  803.     RPC_TIMEDOUT=5,            /* call timed out */
  804.     /*
  805.      * remote errors
  806.      */
  807.     RPC_VERSMISMATCH=6,        /* rpc versions not compatible */
  808.     RPC_AUTHERROR=7,        /* authentication error */
  809.     RPC_PROGUNAVAIL=8,        /* program not available */
  810.     RPC_PROGVERSMISMATCH=9,        /* program version mismatched */
  811.     RPC_PROCUNAVAIL=10,        /* procedure unavailable */
  812.     RPC_CANTDECODEARGS=11,        /* decode arguments error */
  813.     RPC_SYSTEMERROR=12,        /* generic "other problem" */
  814.  
  815.     /*
  816.      * callrpc errors
  817.      */
  818.     RPC_UNKNOWNHOST=13,        /* unknown host name */
  819.  
  820.     /*
  821.      * _ create errors
  822.      */
  823.     RPC_PMAPFAILURE=14,        /* the pmapper failed in its call */
  824.     RPC_PROGNOTREGISTERED=15,    /* remote program is not registered */
  825.     /*
  826.      * unspecified error
  827.      */
  828.     RPC_FAILED=16
  829. };
  830.  
  831.  
  832. /*
  833.  * Error info.
  834.  */
  835. struct rpc_err {
  836.     enum clnt_stat re_status;
  837.     union {
  838.         int RE_errno;        /* realated system error */
  839.         enum auth_stat RE_why;    /* why the auth error occurred */
  840.         struct {
  841.             u_long low;    /* lowest verion supported */
  842.             u_long high;    /* highest verion supported */
  843.         } RE_vers;
  844.         struct {        /* maybe meaningful if RPC_FAILED */
  845.             long s1;
  846.             long s2;
  847.         } RE_lb;        /* life boot & debugging only */
  848.     } ru;
  849. #define    re_errno    ru.RE_errno
  850. #define    re_why        ru.RE_why
  851. #define    re_vers        ru.RE_vers
  852. #define    re_lb        ru.RE_lb
  853. };
  854.  
  855.  
  856. /*
  857.  * Client rpc handle.
  858.  * Created by individual implementations, see e.g. rpc_udp.c.
  859.  * Client is responsible for initializing auth, see e.g. auth_none.c.
  860.  */
  861. typedef struct {
  862.     AUTH    *cl_auth;            /* authenticator */
  863.     struct clnt_ops {
  864.         enum clnt_stat    (*cl_call)();    /* call remote procedure */
  865.         void        (*cl_abort)();    /* abort a call */
  866.         void        (*cl_geterr)();    /* get specific error code */
  867.         bool_t        (*cl_freeres)(); /* frees results */
  868.         void        (*cl_destroy)();/* destroy this structure */
  869.     } *cl_ops;
  870.     caddr_t            cl_private;    /* private stuff */
  871. } CLIENT;
  872.  
  873.  
  874. /*
  875.  * client side rpc interface ops
  876.  *
  877.  * Parameter types are:
  878.  *
  879.  */
  880.  
  881. /*
  882.  * enum clnt_stat
  883.  * CLNT_CALL(rh, proc, xargs, argsp, xres, resp, timeout)
  884.  *     CLIENT *rh;
  885.  *    u_long proc;
  886.  *    xdrproc_t xargs;
  887.  *    caddr_t argsp;
  888.  *    xdrproc_t xres;
  889.  *    caddr_t resp;
  890.  *    struct timeval  timeout;
  891.  */
  892. #define    CLNT_CALL(rh, proc, xargs, argsp, xres, resp, secs)    \
  893.     ((*(rh)->cl_ops->cl_call)(rh, proc, xargs, argsp, xres, resp, secs))
  894. #define    clnt_call(rh, proc, xargs, argsp, xres, resp, secs)    \
  895.     ((*(rh)->cl_ops->cl_call)(rh, proc, xargs, argsp, xres, resp, secs))
  896.  
  897. /*
  898.  * void
  899.  * CLNT_ABORT(rh);
  900.  *     CLIENT *rh;
  901.  */
  902. #define    CLNT_ABORT(rh)    ((*(rh)->cl_ops->cl_abort)(rh))
  903. #define    clnt_abort(rh)    ((*(rh)->cl_ops->cl_abort)(rh))
  904.  
  905. /*
  906.  * struct rpc_err
  907.  * CLNT_GETERR(rh);
  908.  *     CLIENT *rh;
  909.  */
  910. #define    CLNT_GETERR(rh,errp)    ((*(rh)->cl_ops->cl_geterr)(rh, errp))
  911. #define    clnt_geterr(rh,errp)    ((*(rh)->cl_ops->cl_geterr)(rh, errp))
  912.  
  913.  
  914. /*
  915.  * bool_t
  916.  * CLNT_FREERES(rh, xres, resp);
  917.  *     CLIENT *rh;
  918.  *    xdrproc_t xres;
  919.  *    caddr_t resp;
  920.  */
  921. #define    CLNT_FREERES(rh,xres,resp) ((*(rh)->cl_ops->cl_freeres)(rh,xres,resp))
  922. #define    clnt_freeres(rh,xres,resp) ((*(rh)->cl_ops->cl_freeres)(rh,xres,resp))
  923.  
  924. /*
  925.  * void
  926.  * CLNT_DESTROY(rh);
  927.  *     CLIENT *rh;
  928.  */
  929. #define    CLNT_DESTROY(rh)    ((*(rh)->cl_ops->cl_destroy)(rh))
  930. #define    clnt_destroy(rh)    ((*(rh)->cl_ops->cl_destroy)(rh))
  931.  
  932.  
  933. /*
  934.  * RPCTEST is a test program which is accessable on every rpc
  935.  * transport/port.  It is used for testing, performance evaluation,
  936.  * and network administration.
  937.  */
  938.  
  939. #define RPCTEST_PROGRAM        ((u_long)1)
  940. #define RPCTEST_VERSION        ((u_long)1)
  941. #define RPCTEST_NULL_PROC    ((u_long)2)
  942. #define RPCTEST_NULL_BATCH_PROC    ((u_long)3)
  943.  
  944. /*
  945.  * By convention, procedure 0 takes null arguments and returns them
  946.  */
  947.  
  948. #define NULLPROC ((u_long)0)
  949.  
  950. /*
  951.  * Below are the client handle creation routines for the various
  952.  * implementations of client side rpc.  They can return NULL if a 
  953.  * creation failure occurs.
  954.  */
  955.  
  956. /*
  957.  * Memory based rpc (for speed check and testing)
  958.  * CLIENT *
  959.  * clntraw_create(prog, vers)
  960.  *    u_long prog;
  961.  *    u_long vers;
  962.  */
  963. extern CLIENT *clntraw_create();
  964.  
  965. /*
  966.  * UDP based rpc.
  967.  * CLIENT *
  968.  * clntudp_create(raddr, program, version, wait, sockp)
  969.  *    struct sockaddr_in *raddr;
  970.  *    u_long program;
  971.  *    u_long version;
  972.  *    struct timeval wait;
  973.  *    int *sockp;
  974.  */
  975. extern CLIENT *clntudp_create();
  976. #define UDPMSGSIZE 8800
  977.  
  978. /*
  979.  * TCP based rpc
  980.  * CLIENT *
  981.  * clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz)
  982.  *    struct sockaddr_in *raddr;
  983.  *    u_long prog;
  984.  *    u_long version;
  985.  *    register int *sockp;
  986.  *    u_int sendsz;
  987.  *    u_int recvsz;
  988.  */
  989. extern CLIENT *clnttcp_create();
  990.  
  991.  
  992. /* 
  993.  * If a creation fails, the following allows the user to figure out why.
  994.  */
  995. struct rpc_createerr {
  996.     enum clnt_stat cf_stat;
  997.     struct rpc_err cf_error; /* useful when cf_stat == RPC_PMAPFAILURE */
  998. };
  999.  
  1000. extern struct rpc_createerr rpc_createerr;
  1001.  
  1002. !Funky!Stuff!
  1003. echo x - clnt_perror.c
  1004. sed 's/^X//' >clnt_perror.c <<'!Funky!Stuff!'
  1005. /*
  1006.  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  1007.  * unrestricted use provided that this legend is included on all tape
  1008.  * media and as a part of the software program in whole or part.  Users
  1009.  * may copy or modify Sun RPC without charge, but are not authorized
  1010.  * to license or distribute it to anyone else except as part of a product or
  1011.  * program developed by the user.
  1012.  * 
  1013.  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  1014.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  1015.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  1016.  * 
  1017.  * Sun RPC is provided with no support and without any obligation on the
  1018.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  1019.  * modification or enhancement.
  1020.  * 
  1021.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  1022.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  1023.  * OR ANY PART THEREOF.
  1024.  * 
  1025.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  1026.  * or profits or other special, indirect and consequential damages, even if
  1027.  * Sun has been advised of the possibility of such damages.
  1028.  * 
  1029.  * Sun Microsystems, Inc.
  1030.  * 2550 Garcia Avenue
  1031.  * Mountain View, California  94043
  1032.  */
  1033. #ifndef lint
  1034. static char sccsid[] = "@(#)clnt_perror.c 1.1 85/02/08 Copyr 1984 Sun Micro";
  1035. #endif
  1036.  
  1037. /*
  1038.  * clnt_perror.c
  1039.  *
  1040.  * Copyright (C) 1984, Sun Microsystems, Inc.
  1041.  *
  1042.  */
  1043. #include "types.h"
  1044. #include "xdr.h"
  1045. #include "auth.h"
  1046. #include "clnt.h"
  1047. #include "rpc_msg.h"
  1048. #include <stdio.h>
  1049. extern char *sys_errlist[];
  1050.  
  1051. /*
  1052.  * Print reply error info
  1053.  */
  1054. void
  1055. clnt_perror(rpch, s)
  1056.     CLIENT *rpch;
  1057.     char *s;
  1058. {
  1059.     struct rpc_err e;
  1060.     void clnt_perrno();
  1061.  
  1062.     CLNT_GETERR(rpch, &e);
  1063.     fprintf(stderr, "%s: ", s);
  1064.     switch (e.re_status) {
  1065.         case RPC_SUCCESS:
  1066.         case RPC_CANTENCODEARGS:
  1067.         case RPC_CANTDECODERES:
  1068.         case RPC_TIMEDOUT:
  1069.         case RPC_PROGUNAVAIL:
  1070.         case RPC_PROCUNAVAIL:
  1071.         case RPC_CANTDECODEARGS:
  1072.             clnt_perrno(e.re_status);
  1073.             break;
  1074.         case RPC_CANTSEND:
  1075.             clnt_perrno(e.re_status);
  1076.             fprintf(stderr, "; errno = %s",
  1077.                 sys_errlist[e.re_errno]);
  1078.             break;
  1079.     
  1080.         case RPC_CANTRECV:
  1081.             clnt_perrno(e.re_status);
  1082.             fprintf(stderr, "; errno = %s",
  1083.                 sys_errlist[e.re_errno]);
  1084.             break;
  1085.     
  1086.         case RPC_VERSMISMATCH:
  1087.             clnt_perrno(e.re_status);
  1088.             fprintf(stderr, "; low version = %lu, high version = %lu", e.re_vers.low, e.re_vers.high);
  1089.             break;
  1090.     
  1091.         case RPC_AUTHERROR:
  1092.             clnt_perrno(e.re_status);
  1093.             fprintf(stderr, "; why = ");
  1094.             switch (e.re_why) {
  1095.             case AUTH_OK:
  1096.                 fprintf(stderr, "AUTH_OK");
  1097.                 break;
  1098.     
  1099.             case AUTH_BADCRED:
  1100.                 fprintf(stderr, "AUTH_BOGUS_CREDENTIAL");
  1101.                 break;
  1102.     
  1103.             case AUTH_REJECTEDCRED:
  1104.                 fprintf(stderr, "AUTH_REJECTED_CREDENTIAL");
  1105.                 break;
  1106.     
  1107.             case AUTH_BADVERF:
  1108.                 fprintf(stderr, "AUTH_BOGUS_VERIFIER");
  1109.                 break;
  1110.     
  1111.             case AUTH_REJECTEDVERF:
  1112.                 fprintf(stderr, "AUTH_REJECTED_VERIFIER");
  1113.                 break;
  1114.     
  1115.             case AUTH_TOOWEAK:
  1116.                 fprintf(stderr, "AUTH_TOO_WEAK (remote error)");
  1117.                 break;
  1118.     
  1119.             case AUTH_INVALIDRESP:
  1120.                 fprintf(stderr, "AUTH_INVALID_RESPONSE");
  1121.                 break;
  1122.     
  1123.             default:
  1124.                 fprintf(stderr, "AUTH_UNKNOWN_FAILURE");
  1125.                 break;
  1126.             }
  1127.             break;
  1128.     
  1129.         case RPC_PROGVERSMISMATCH:
  1130.             clnt_perrno(e.re_status);
  1131.             fprintf(stderr, "; low version = %lu, high version = %lu", e.re_vers.low, e.re_vers.high);
  1132.             break;
  1133.     
  1134.         default:
  1135.             fprintf(stderr, "RPC_UNKNOWN_FAILURE; s1 = %lu, s2 = %lu", e.re_lb.s1, e.re_lb.s2);
  1136.             break;
  1137.     }
  1138.     fprintf(stderr, "\n");
  1139. }
  1140.  
  1141. /*
  1142.  * This interface for use by clntrpc
  1143.  */
  1144. void
  1145. clnt_perrno(num)
  1146.     enum clnt_stat num;
  1147. {
  1148.     switch (num) {
  1149.         case RPC_SUCCESS:
  1150.             fprintf(stderr, "RPC_SUCCESS");
  1151.             break;
  1152.     
  1153.         case RPC_CANTENCODEARGS:
  1154.             fprintf(stderr, "RPC_CANT_ENCODE_ARGS");
  1155.             break;
  1156.     
  1157.         case RPC_CANTDECODERES:
  1158.             fprintf(stderr, "RPC_CANT_DECODE_RESULTS");
  1159.             break;
  1160.     
  1161.         case RPC_CANTSEND:
  1162.             fprintf(stderr, "RPC_CANT_SEND");
  1163.             break;
  1164.     
  1165.         case RPC_CANTRECV:
  1166.             fprintf(stderr, "RPC_CANT_RECV");
  1167.             break;
  1168.     
  1169.         case RPC_TIMEDOUT:
  1170.             fprintf(stderr, "RPC_TIMED_OUT");
  1171.             break;
  1172.     
  1173.         case RPC_VERSMISMATCH:
  1174.             fprintf(stderr, "RPC_VERSION_MISMATCH");
  1175.             break;
  1176.     
  1177.         case RPC_AUTHERROR:
  1178.             fprintf(stderr, "RPC_AUTH_ERROR");
  1179.             break;
  1180.     
  1181.         case RPC_PROGUNAVAIL:
  1182.             fprintf(stderr, "RPC_REMOTE_PROGRAM_UNAVAILABLE");
  1183.             break;
  1184.     
  1185.         case RPC_PROGVERSMISMATCH:
  1186.             fprintf(stderr, "RPC_PROGRAM_MISMATCH");
  1187.             break;
  1188.     
  1189.         case RPC_PROCUNAVAIL:
  1190.             fprintf(stderr, "RPC_UNKNOWN_PROCEDURE");
  1191.             break;
  1192.     
  1193.         case RPC_CANTDECODEARGS:
  1194.             fprintf(stderr, "RPC_CANT_DECODE_ARGS");
  1195.             break;
  1196.         case RPC_UNKNOWNHOST:
  1197.             fprintf(stderr, "RPC_UNKNOWNHOST");
  1198.             break;
  1199.         case RPC_PMAPFAILURE:
  1200.             fprintf(stderr, "RPC_PMAP_FAILURE");
  1201.             break;
  1202.         case RPC_PROGNOTREGISTERED:
  1203.             fprintf(stderr, "RPC_PROG_NOT_REGISTERED");
  1204.             break;
  1205.         case RPC_SYSTEMERROR:
  1206.             fprintf(stderr, "RPC_SYSTEM_ERROR");
  1207.             break;
  1208.     }
  1209. }
  1210.  
  1211. /*
  1212.  * A handle on why an rpc creation routine failed (returned NULL.)
  1213.  */
  1214. struct rpc_createerr rpc_createerr;
  1215.  
  1216. clnt_pcreateerror(s)
  1217.     char *s;
  1218. {
  1219.  
  1220.     fprintf(stderr, "%s: ", s);
  1221.     clnt_perrno(rpc_createerr.cf_stat);
  1222.     switch (rpc_createerr.cf_stat) {
  1223.         case RPC_PMAPFAILURE:
  1224.             fprintf(stderr, " - ");
  1225.             clnt_perrno(rpc_createerr.cf_error.re_status);
  1226.             break;
  1227.  
  1228.         case RPC_SYSTEMERROR:
  1229.             fprintf(stderr, " - %s", sys_errlist[rpc_createerr.cf_error.re_errno]);
  1230.             break;
  1231.  
  1232.     }
  1233.     fprintf(stderr, "\n");
  1234. }
  1235. !Funky!Stuff!
  1236. echo x - clnt_raw.c
  1237. sed 's/^X//' >clnt_raw.c <<'!Funky!Stuff!'
  1238. /*
  1239.  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  1240.  * unrestricted use provided that this legend is included on all tape
  1241.  * media and as a part of the software program in whole or part.  Users
  1242.  * may copy or modify Sun RPC without charge, but are not authorized
  1243.  * to license or distribute it to anyone else except as part of a product or
  1244.  * program developed by the user.
  1245.  * 
  1246.  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  1247.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  1248.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  1249.  * 
  1250.  * Sun RPC is provided with no support and without any obligation on the
  1251.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  1252.  * modification or enhancement.
  1253.  * 
  1254.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  1255.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  1256.  * OR ANY PART THEREOF.
  1257.  * 
  1258.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  1259.  * or profits or other special, indirect and consequential damages, even if
  1260.  * Sun has been advised of the possibility of such damages.
  1261.  * 
  1262.  * Sun Microsystems, Inc.
  1263.  * 2550 Garcia Avenue
  1264.  * Mountain View, California  94043
  1265.  */
  1266. #ifndef lint
  1267. static char sccsid[] = "@(#)clnt_raw.c 1.4 85/03/17 Copyr 1984 Sun Micro";
  1268. #endif
  1269.  
  1270. /*
  1271.  * clnt_raw.c
  1272.  *
  1273.  * Copyright (C) 1984, Sun Microsystems, Inc.
  1274.  *
  1275.  * Memory based rpc for simple testing and timing.
  1276.  * Interface to create an rpc client and server in the same process.
  1277.  * This lets us similate rpc and get round trip overhead, without
  1278.  * any interference from the kernal.
  1279.  */
  1280.  
  1281. #include "types.h"
  1282. #include <sys/time.h>
  1283. #include <netinet/in.h>
  1284. #include "xdr.h"
  1285. #include "auth.h"
  1286. #include "clnt.h"
  1287. #include "rpc_msg.h"
  1288.  
  1289. #define NULL ((caddr_t)0)
  1290. #define MCALL_MSG_SIZE 24
  1291.  
  1292. /*
  1293.  * This is the "network" we will be moving stuff over.
  1294.  */
  1295. char _raw_buf[UDPMSGSIZE];
  1296.  
  1297. static char    mashl_callmsg[MCALL_MSG_SIZE];
  1298. static u_int    mcnt;
  1299.  
  1300. static enum clnt_stat    clntraw_call();
  1301. static void        clntraw_abort();
  1302. static void        clntraw_geterr();
  1303. static bool_t        clntraw_freeres();
  1304. static void        clntraw_destroy();
  1305.  
  1306. static struct clnt_ops client_ops = {
  1307.     clntraw_call,
  1308.     clntraw_abort,
  1309.     clntraw_geterr,
  1310.     clntraw_freeres,
  1311.     clntraw_destroy
  1312. };
  1313.  
  1314. static CLIENT    client_object;
  1315. static CLIENT    *client = &client_object;
  1316. static XDR    xdr_stream;
  1317.  
  1318. void    svc_getreq();
  1319.  
  1320. /*
  1321.  * Create a client handle for memory based rpc.
  1322.  */
  1323. CLIENT *
  1324. clntraw_create(prog, vers)
  1325.     u_long prog;
  1326.     u_long vers;
  1327. {
  1328.     struct rpc_msg call_msg;
  1329.     XDR *xdrs = &xdr_stream;
  1330.  
  1331.     /*
  1332.      * pre-serialize the staic part of the call msg and stash it away
  1333.      */
  1334.     call_msg.rm_direction = CALL;
  1335.     call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
  1336.     call_msg.rm_call.cb_prog = prog;
  1337.     call_msg.rm_call.cb_vers = vers;
  1338.     xdrmem_create(xdrs, mashl_callmsg, MCALL_MSG_SIZE, XDR_ENCODE); 
  1339.     if (! xdr_callhdr(xdrs, &call_msg)) {
  1340.         perror("clnt_raw.c - Fatal header serialization error.");
  1341.     }
  1342.     mcnt = XDR_GETPOS(xdrs);
  1343.     XDR_DESTROY(xdrs);
  1344.  
  1345.     /*
  1346.      * Set xdrmem for client/server shared buffer
  1347.      */
  1348.     xdrmem_create(xdrs, _raw_buf, UDPMSGSIZE, XDR_FREE);
  1349.  
  1350.     /*
  1351.      * create client handle
  1352.      */
  1353.     client->cl_ops = &client_ops;
  1354.     client->cl_auth = authnone_create();
  1355.     return (client);
  1356. }
  1357.  
  1358. static enum clnt_stat 
  1359. clntraw_call(h, proc, xargs, argsp, xresults, resultsp, timeout)
  1360.     CLIENT *h;
  1361.     u_long proc;
  1362.     xdrproc_t xargs;
  1363.     caddr_t argsp;
  1364.     xdrproc_t xresults;
  1365.     caddr_t resultsp;
  1366.     struct timeval timeout;
  1367. {
  1368.     register XDR *xdrs = &xdr_stream;
  1369.     struct rpc_msg msg;
  1370.     enum clnt_stat status;
  1371.     struct rpc_err error;
  1372.  
  1373. call_again:
  1374.     /*
  1375.      * send request
  1376.      */
  1377.     xdrs->x_op = XDR_ENCODE;
  1378.     XDR_SETPOS(xdrs, 0);
  1379.     ((struct rpc_msg *)mashl_callmsg)->rm_xid ++ ;
  1380.     if ((! XDR_PUTBYTES(xdrs, mashl_callmsg, mcnt)) ||
  1381.         (! XDR_PUTLONG(xdrs, (long *)&proc)) ||
  1382.         (! AUTH_MARSHALL(h->cl_auth, xdrs)) ||
  1383.         (! (*xargs)(xdrs, argsp))) {
  1384.         return (RPC_CANTENCODEARGS);
  1385.     }
  1386.     (void)XDR_GETPOS(xdrs);  /* called just to cause overhead */
  1387.  
  1388.     /*
  1389.      * We have to call server input routine here because this is
  1390.      * all going on in one process. Yuk.
  1391.      */
  1392.     svc_getreq(1);
  1393.  
  1394.     /*
  1395.      * get results
  1396.      */
  1397.     xdrs->x_op = XDR_DECODE;
  1398.     XDR_SETPOS(xdrs, 0);
  1399.     msg.acpted_rply.ar_verf = _null_auth;
  1400.     msg.acpted_rply.ar_results.where = resultsp;
  1401.     msg.acpted_rply.ar_results.proc = xresults;
  1402.     if (! xdr_replymsg(xdrs, &msg))
  1403.         return (RPC_CANTDECODERES);
  1404.     _seterr_reply(&msg, &error);
  1405.     status = error.re_status;
  1406.  
  1407.     if (status == RPC_SUCCESS) {
  1408.         if (! AUTH_VALIDATE(h->cl_auth, &msg.acpted_rply.ar_verf)) {
  1409.             status = RPC_AUTHERROR;
  1410.         }
  1411.     }  /* end successful completion */
  1412.     else {
  1413.         if (AUTH_REFRESH(h->cl_auth))
  1414.             goto call_again;
  1415.     }  /* end of unsuccessful completion */
  1416.  
  1417.     if (status == RPC_SUCCESS) {
  1418.         if (! AUTH_VALIDATE(h->cl_auth, &msg.acpted_rply.ar_verf)) {
  1419.             status = RPC_AUTHERROR;
  1420.         }
  1421.         if (msg.acpted_rply.ar_verf.oa_base != NULL) {
  1422.             xdrs->x_op = XDR_FREE;
  1423.             (void)xdr_opaque_auth(xdrs, &(msg.acpted_rply.ar_verf));
  1424.         }
  1425.     }
  1426.  
  1427.     return (status);
  1428. }
  1429.  
  1430. static void
  1431. clntraw_geterr()
  1432. {
  1433. }
  1434.  
  1435.  
  1436. static bool_t
  1437. clntraw_freeres(cl, xdr_res, res_ptr)
  1438.     CLIENT *cl;
  1439.     xdrproc_t xdr_res;
  1440.     caddr_t res_ptr;
  1441. {
  1442.     register XDR *xdrs = &xdr_stream;
  1443.  
  1444.     xdrs->x_op = XDR_FREE;
  1445.     return ((*xdr_res)(xdrs, res_ptr));
  1446. }
  1447.  
  1448. static void
  1449. clntraw_abort()
  1450. {
  1451. }
  1452.  
  1453. static void
  1454. clntraw_destroy()
  1455. {
  1456. }
  1457. !Funky!Stuff!
  1458. echo x - clnt_simple.c
  1459. sed 's/^X//' >clnt_simple.c <<'!Funky!Stuff!'
  1460. /*
  1461.  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  1462.  * unrestricted use provided that this legend is included on all tape
  1463.  * media and as a part of the software program in whole or part.  Users
  1464.  * may copy or modify Sun RPC without charge, but are not authorized
  1465.  * to license or distribute it to anyone else except as part of a product or
  1466.  * program developed by the user.
  1467.  * 
  1468.  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  1469.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  1470.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  1471.  * 
  1472.  * Sun RPC is provided with no support and without any obligation on the
  1473.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  1474.  * modification or enhancement.
  1475.  * 
  1476.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  1477.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  1478.  * OR ANY PART THEREOF.
  1479.  * 
  1480.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  1481.  * or profits or other special, indirect and consequential damages, even if
  1482.  * Sun has been advised of the possibility of such damages.
  1483.  * 
  1484.  * Sun Microsystems, Inc.
  1485.  * 2550 Garcia Avenue
  1486.  * Mountain View, California  94043
  1487.  */
  1488. #ifndef lint
  1489. static char sccsid[] = "@(#)clnt_simple.c 1.1 84/12/20 Copyr 1984 Sun Micro";
  1490. #endif
  1491.  
  1492. /* 
  1493.  * clnt_simple.c
  1494.  * Simplified front end to rpc.
  1495.  *
  1496.  * Copyright (C) 1984, Sun Microsystems, Inc.
  1497.  */
  1498.  
  1499. #include <stdio.h>
  1500. #include <rpc/rpc.h>
  1501. #include <sys/socket.h>
  1502. #include <sys/time.h>
  1503. #include <netdb.h>
  1504.  
  1505. callrpc(host, prognum, versnum, procnum, inproc, in, outproc, out)
  1506.     char *host;
  1507.     xdrproc_t inproc, outproc;
  1508.     char *in, *out;
  1509. {
  1510.     struct sockaddr_in server_addr;
  1511.     enum clnt_stat clnt_stat;
  1512.     struct hostent *hp;
  1513.     struct timeval timeout, tottimeout;
  1514.  
  1515.     static CLIENT *client;
  1516.     static int socket = RPC_ANYSOCK;
  1517.     static int oldprognum, oldversnum, valid;
  1518.     static char oldhost[256];
  1519.  
  1520.     if (valid && oldprognum == prognum && oldversnum == versnum
  1521.         && strcmp(oldhost, host) == 0) {
  1522.         /* reuse old client */        
  1523.     }
  1524.     else {
  1525.         close(socket);
  1526.         socket = RPC_ANYSOCK;
  1527.         if (client) {
  1528.             clnt_destroy(client);
  1529.             client = NULL;
  1530.         }
  1531.         if ((hp = gethostbyname(host)) == NULL)
  1532.             return ((int) RPC_UNKNOWNHOST);
  1533.         timeout.tv_usec = 0;
  1534.         timeout.tv_sec = 10;
  1535.         bcopy(hp->h_addr, &server_addr.sin_addr, hp->h_length);
  1536.         server_addr.sin_family = AF_INET;
  1537.         server_addr.sin_port =  0;
  1538.         if ((client = clntudp_create(&server_addr, prognum,
  1539.             versnum, timeout, &socket)) == NULL)
  1540.             return ((int) rpc_createerr.cf_stat);
  1541.         valid = 1;
  1542.         oldprognum = prognum;
  1543.         oldversnum = versnum;
  1544.         strcpy(oldhost, host);
  1545.     }
  1546.     tottimeout.tv_sec = 25;
  1547.     tottimeout.tv_usec = 0;
  1548.     clnt_stat = clnt_call(client, procnum, inproc, in,
  1549.         outproc, out, tottimeout);
  1550.     /* 
  1551.      * if call failed, empty cache
  1552.      */
  1553.     if (clnt_stat != RPC_SUCCESS)
  1554.         valid = 0;
  1555.     return ((int) clnt_stat);
  1556. }
  1557. !Funky!Stuff!
  1558. echo x - clnt_tcp.c
  1559. sed 's/^X//' >clnt_tcp.c <<'!Funky!Stuff!'
  1560. /*
  1561.  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  1562.  * unrestricted use provided that this legend is included on all tape
  1563.  * media and as a part of the software program in whole or part.  Users
  1564.  * may copy or modify Sun RPC without charge, but are not authorized
  1565.  * to license or distribute it to anyone else except as part of a product or
  1566.  * program developed by the user.
  1567.  * 
  1568.  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  1569.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  1570.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  1571.  * 
  1572.  * Sun RPC is provided with no support and without any obligation on the
  1573.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  1574.  * modification or enhancement.
  1575.  * 
  1576.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  1577.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  1578.  * OR ANY PART THEREOF.
  1579.  * 
  1580.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  1581.  * or profits or other special, indirect and consequential damages, even if
  1582.  * Sun has been advised of the possibility of such damages.
  1583.  * 
  1584.  * Sun Microsystems, Inc.
  1585.  * 2550 Garcia Avenue
  1586.  * Mountain View, California  94043
  1587.  */
  1588. #ifndef lint
  1589. static char sccsid[] = "@(#)clnt_tcp.c 1.5 85/03/17 Copyr 1984 Sun Micro";
  1590. #endif
  1591.  
  1592. /*
  1593.  * clnt_tcp.c, Implements a TCP/IP based, client side RPC.
  1594.  *
  1595.  * Copyright (C) 1984, Sun Microsystems, Inc.
  1596.  *
  1597.  * TCP based RPC supports 'batched calls'.
  1598.  * A sequence of calls may be batched-up in a send buffer.  The rpc call
  1599.  * return immediately to the client even though the call was not necessarily
  1600.  * sent.  The batching occurs iff the results' xdr routine is NULL (0) AND
  1601.  * the rpc timeout value is zero (see clnt.h, rpc).
  1602.  *
  1603.  * Clients should NOT casually batch calls that in fact return results; that is,
  1604.  * the server side should be aware that a call is batched and not produce any
  1605.  * return message.  Batched calls that produce many result messages can
  1606.  * deadlock (netlock) the client and the server....
  1607.  *
  1608.  * Now go hang yourself.
  1609.  */
  1610.  
  1611. #include <stdio.h>
  1612. #include "types.h"
  1613. #include <sys/socket.h>
  1614. #include <sys/time.h>
  1615. #include <netinet/in.h>
  1616. #include <netdb.h>
  1617. #include <errno.h>
  1618. #include "xdr.h"
  1619. #include "auth.h"
  1620. #include "clnt.h"
  1621. #include "rpc_msg.h"
  1622. #include "pmap_clnt.h"
  1623.  
  1624. #define MCALL_MSG_SIZE 24
  1625.  
  1626. char *malloc();
  1627. extern int errno;
  1628. long random();
  1629.  
  1630. static int    readtcp();
  1631. static int    writetcp();
  1632.  
  1633. static enum clnt_stat    clnttcp_call();
  1634. static void        clnttcp_abort();
  1635. static void        clnttcp_geterr();
  1636. static bool_t        clnttcp_freeres();
  1637. static void        clnttcp_destroy();
  1638.  
  1639. static struct clnt_ops tcp_ops = {
  1640.     clnttcp_call,
  1641.     clnttcp_abort,
  1642.     clnttcp_geterr,
  1643.     clnttcp_freeres,
  1644.     clnttcp_destroy
  1645. };
  1646.  
  1647. struct ct_data {
  1648.     int        ct_sock;
  1649.     struct timeval    ct_wait;
  1650.     struct rpc_err    ct_error;
  1651.     char        ct_mcall[MCALL_MSG_SIZE];    /* marshalled callmsg */
  1652.     u_int        ct_mpos;            /* pos after marshal */
  1653.     XDR        ct_xdrs;
  1654. };
  1655.  
  1656. /*
  1657.  * Create a client handle for a tcp/ip connection.
  1658.  * If *sockp<0, *sockp is set to a newly created TCP socket and it is
  1659.  * connected to raddr.  If *sockp non-negative then
  1660.  * raddr is ignored.  The rpc/tcp package does buffering
  1661.  * similar to stdio, so the client must pick send and receive buffer sizes,];
  1662.  * 0 => use the default.
  1663.  * If raddr->sin_port is 0, then a binder on the remote machine is
  1664.  * consulted for the right port number.
  1665.  * NB: *sockp is copied into a private area.
  1666.  * NB: It is the clients responsibility to close *sockp.
  1667.  * NB: The rpch->cl_auth is set null authentication.  Caller may wish to set this
  1668.  * something more useful.
  1669.  */
  1670. CLIENT *
  1671. clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz)
  1672.     struct sockaddr_in *raddr;
  1673.     u_long prog;
  1674.     u_long vers;
  1675.     register int *sockp;
  1676.     u_int sendsz;
  1677.     u_int recvsz;
  1678. {
  1679.     CLIENT *h;
  1680.     register struct ct_data *ct;
  1681.     struct timeval now;
  1682.     struct rpc_msg call_msg;
  1683.  
  1684.     h  = (CLIENT *)mem_alloc(sizeof(*h));
  1685.     if (h == NULL) {
  1686.         fprintf(stderr, "clnttcp_create: out of memory\n");
  1687.         rpc_createerr.cf_stat = RPC_SYSTEMERROR;
  1688.         rpc_createerr.cf_error.re_errno = errno;
  1689.         goto fooy;
  1690.     }
  1691.     ct = (struct ct_data *)mem_alloc(sizeof(*ct));
  1692.     if (ct == NULL) {
  1693.         fprintf(stderr, "clnttcp_create: out of memory\n");
  1694.         rpc_createerr.cf_stat = RPC_SYSTEMERROR;
  1695.         rpc_createerr.cf_error.re_errno = errno;
  1696.         goto fooy;
  1697.     }
  1698.  
  1699.     /*
  1700.      * If no port number given ask the pmap for one
  1701.      */
  1702.     if (raddr->sin_port == 0) {
  1703.         u_short port;
  1704.         if ((port = pmap_getport(raddr, prog, vers, IPPROTO_TCP)) == 0) {
  1705.             mem_free((caddr_t)ct, sizeof(struct ct_data));
  1706.             mem_free((caddr_t)h, sizeof(CLIENT));
  1707.             return ((CLIENT *)NULL);
  1708.         }
  1709.         raddr->sin_port = htons(port);
  1710.     }
  1711.  
  1712.     /*
  1713.      * If no socket given, open one
  1714.      */
  1715.     if (*sockp < 0) {
  1716.         if (((*sockp = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
  1717.             || (connect(*sockp, (struct sockaddr *)raddr,
  1718.             sizeof(*raddr)) < 0)) {
  1719.             rpc_createerr.cf_stat = RPC_SYSTEMERROR;
  1720.             rpc_createerr.cf_error.re_errno = errno;
  1721.             goto fooy;
  1722.         }
  1723.     }
  1724.  
  1725.     /*
  1726.      * Set up private data struct
  1727.      */
  1728.     ct->ct_sock = *sockp;
  1729.     ct->ct_wait.tv_usec = 0;
  1730.  
  1731.     /*
  1732.      * Initialize call message
  1733.      */
  1734.     (void)gettimeofday(&now, (struct timezone *)0);
  1735.     call_msg.rm_xid = getpid() ^ (int)random() ^ now.tv_sec ^ now.tv_usec;
  1736.     call_msg.rm_direction = CALL;
  1737.     call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
  1738.     call_msg.rm_call.cb_prog = prog;
  1739.     call_msg.rm_call.cb_vers = vers;
  1740.  
  1741.     /*
  1742.      * pre-serialize the staic part of the call msg and stash it away
  1743.      */
  1744.     xdrmem_create(&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE,
  1745.         XDR_ENCODE);
  1746.     if (! xdr_callhdr(&(ct->ct_xdrs), &call_msg)) {
  1747.         goto fooy;
  1748.     }
  1749.     ct->ct_mpos = XDR_GETPOS(&(ct->ct_xdrs));
  1750.     XDR_DESTROY(&(ct->ct_xdrs));
  1751.  
  1752.     /*
  1753.      * Create a client handle which uses xdrrec for serialization
  1754.      * and authnone for authentication.
  1755.      */
  1756.     xdrrec_create(&(ct->ct_xdrs), sendsz, recvsz,
  1757.         (caddr_t)ct, readtcp, writetcp);
  1758.     h->cl_ops = &tcp_ops;
  1759.     h->cl_private = (caddr_t) ct;
  1760.     h->cl_auth = authnone_create();
  1761.     return (h);
  1762.  
  1763. fooy:
  1764.     /*
  1765.      * Something goofed, free stuff and barf
  1766.      */
  1767.     mem_free((caddr_t)ct, sizeof(struct ct_data));
  1768.     mem_free((caddr_t)h, sizeof(CLIENT));
  1769.     (void)close(*sockp);
  1770.     return ((CLIENT *)NULL);
  1771. }
  1772.  
  1773. static enum clnt_stat
  1774. clnttcp_call(h, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout)
  1775.     register CLIENT *h;
  1776.     u_long proc;
  1777.     xdrproc_t xdr_args;
  1778.     caddr_t args_ptr;
  1779.     xdrproc_t xdr_results;
  1780.     caddr_t results_ptr;
  1781.     struct timeval timeout;
  1782. {
  1783.     register struct ct_data *ct = (struct ct_data *) h->cl_private;
  1784.     register XDR *xdrs = &(ct->ct_xdrs);
  1785.     struct rpc_msg reply_msg;
  1786.     u_long x_id;
  1787.     u_long *msg_x_id = (u_long *)(ct->ct_mcall);    /* yuk */
  1788.     register bool_t shipnow;
  1789.  
  1790.     ct->ct_wait = timeout;
  1791.     shipnow =
  1792.         (xdr_results == (xdrproc_t)0 && timeout.tv_sec == 0
  1793.         && timeout.tv_usec == 0) ? FALSE : TRUE;
  1794.  
  1795. call_again:
  1796.     xdrs->x_op = XDR_ENCODE;
  1797.     ct->ct_error.re_status = RPC_SUCCESS;
  1798.     x_id = ntohl(--(*msg_x_id));
  1799.     if ((! XDR_PUTBYTES(xdrs, ct->ct_mcall, ct->ct_mpos)) ||
  1800.         (! XDR_PUTLONG(xdrs, (long *)&proc)) ||
  1801.         (! AUTH_MARSHALL(h->cl_auth, xdrs)) ||
  1802.         (! (*xdr_args)(xdrs, args_ptr))) {
  1803.         if (ct->ct_error.re_status == RPC_SUCCESS)
  1804.             ct->ct_error.re_status = RPC_CANTENCODEARGS;
  1805.         (void)xdrrec_endofrecord(xdrs, TRUE);
  1806.         return (ct->ct_error.re_status);
  1807.     }
  1808.     if (! xdrrec_endofrecord(xdrs, shipnow))
  1809.         return (ct->ct_error.re_status = RPC_CANTSEND);
  1810.     if (! shipnow)
  1811.         return (RPC_SUCCESS);
  1812.     xdrs->x_op = XDR_DECODE;
  1813.  
  1814.     /*
  1815.      * Keep receiving until we get a valid transaction id
  1816.      */
  1817.     while (TRUE) {
  1818.         reply_msg.acpted_rply.ar_verf = _null_auth;
  1819.         reply_msg.acpted_rply.ar_results.where = NULL;
  1820.         reply_msg.acpted_rply.ar_results.proc = xdr_void;
  1821.         if (! xdrrec_skiprecord(xdrs))
  1822.             return (ct->ct_error.re_status);
  1823.         /* now decode and validate the response header */
  1824.         if (! xdr_replymsg(xdrs, &reply_msg)) {
  1825.             if (ct->ct_error.re_status == RPC_SUCCESS)
  1826.                 continue;
  1827.             return (ct->ct_error.re_status);
  1828.         }
  1829.         if (reply_msg.rm_xid == x_id)
  1830.             break;
  1831.     }
  1832.  
  1833.     /*
  1834.      * process header
  1835.      */
  1836.     _seterr_reply(&reply_msg, &(ct->ct_error));
  1837.     if (ct->ct_error.re_status == RPC_SUCCESS) {
  1838.         if (! AUTH_VALIDATE(h->cl_auth, &reply_msg.acpted_rply.ar_verf)) {
  1839.             ct->ct_error.re_status = RPC_AUTHERROR;
  1840.             ct->ct_error.re_why = AUTH_INVALIDRESP;
  1841.         } else if (! (*xdr_results)(xdrs, results_ptr)) {
  1842.             if (ct->ct_error.re_status == RPC_SUCCESS)
  1843.                 ct->ct_error.re_status = RPC_CANTDECODERES;
  1844.         }
  1845.         /* free verifier ... */
  1846.         if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) {
  1847.             xdrs->x_op = XDR_FREE;
  1848.             (void)xdr_opaque_auth(xdrs, &(reply_msg.acpted_rply.ar_verf));
  1849.         }
  1850.     }  /* end successful completion */
  1851.     else {
  1852.         /* maybe our credentials need to be refreshed ... */
  1853.         if (AUTH_REFRESH(h->cl_auth))
  1854.             goto call_again;
  1855.     }  /* end of unsuccessful completion */
  1856.     return (ct->ct_error.re_status);
  1857. }
  1858.  
  1859. static void
  1860. clnttcp_geterr(h, errp)
  1861.     CLIENT *h;
  1862.     struct rpc_err *errp;
  1863. {
  1864.     register struct ct_data *ct =
  1865.         (struct ct_data *) h->cl_private;
  1866.  
  1867.     *errp = ct->ct_error;
  1868. }
  1869.  
  1870. static bool_t
  1871. clnttcp_freeres(cl, xdr_res, res_ptr)
  1872.     CLIENT *cl;
  1873.     xdrproc_t xdr_res;
  1874.     caddr_t res_ptr;
  1875. {
  1876.     register struct ct_data *ct = (struct ct_data *)cl->cl_private;
  1877.     register XDR *xdrs = &(ct->ct_xdrs);
  1878.  
  1879.     xdrs->x_op = XDR_FREE;
  1880.     return ((*xdr_res)(xdrs, res_ptr));
  1881. }
  1882.  
  1883. static void
  1884. clnttcp_abort()
  1885. {
  1886. }
  1887.  
  1888. static void
  1889. clnttcp_destroy(h)
  1890.     CLIENT *h;
  1891. {
  1892.     register struct ct_data *ct =
  1893.         (struct ct_data *) h->cl_private;
  1894.  
  1895.     XDR_DESTROY(&(ct->ct_xdrs));
  1896.     mem_free((caddr_t)ct, sizeof(struct ct_data));
  1897.     mem_free((caddr_t)h, sizeof(CLIENT));
  1898. }
  1899.  
  1900. /*
  1901.  * Interface between xdr serializer and tcp connection.
  1902.  * Behaves like the system calls, read & write, but keeps some error state
  1903.  * around for the rpc level.
  1904.  */
  1905. static int
  1906. readtcp(ct, buf, len)
  1907.     register struct ct_data *ct;
  1908.     caddr_t buf;
  1909.     register int len;
  1910. {
  1911.     register int mask = 1 << (ct->ct_sock);
  1912.     int readfds;
  1913.  
  1914.     while (TRUE) {
  1915.         readfds = mask;
  1916.         switch (select(32, &readfds, (int*)NULL, (int*)NULL,
  1917.             &(ct->ct_wait))) {
  1918.  
  1919.         case 0:
  1920.             ct->ct_error.re_status = RPC_TIMEDOUT;
  1921.             return (-1);
  1922.  
  1923.         case -1:
  1924.             if (errno == EINTR)
  1925.                 continue;
  1926.             ct->ct_error.re_status = RPC_CANTRECV;
  1927.             ct->ct_error.re_errno = errno;
  1928.             return (-1);
  1929.         }
  1930.         if (readfds == mask)
  1931.             break;
  1932.     }
  1933.     if ((len = read(ct->ct_sock, buf, len)) == -1) {
  1934.         ct->ct_error.re_errno = errno;
  1935.         ct->ct_error.re_status = RPC_CANTRECV;
  1936.     }
  1937.     return (len);
  1938. }
  1939.  
  1940. static int
  1941. writetcp(ct, buf, len)
  1942.     struct ct_data *ct;
  1943.     caddr_t buf;
  1944.     int len;
  1945. {
  1946.     register int i, cnt;
  1947.  
  1948.     for (cnt = len; cnt > 0; cnt -= i, buf += i) {
  1949.         if ((i = write(ct->ct_sock, buf, cnt)) == -1) {
  1950.             ct->ct_error.re_errno = errno;
  1951.             ct->ct_error.re_status = RPC_CANTSEND;
  1952.             return (-1);
  1953.         }
  1954.     }
  1955.     return (len);
  1956. }
  1957. !Funky!Stuff!
  1958. echo x - clnt_udp.c
  1959. sed 's/^X//' >clnt_udp.c <<'!Funky!Stuff!'
  1960. /*
  1961.  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  1962.  * unrestricted use provided that this legend is included on all tape
  1963.  * media and as a part of the software program in whole or part.  Users
  1964.  * may copy or modify Sun RPC without charge, but are not authorized
  1965.  * to license or distribute it to anyone else except as part of a product or
  1966.  * program developed by the user.
  1967.  * 
  1968.  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  1969.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  1970.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  1971.  * 
  1972.  * Sun RPC is provided with no support and without any obligation on the
  1973.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  1974.  * modification or enhancement.
  1975.  * 
  1976.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  1977.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  1978.  * OR ANY PART THEREOF.
  1979.  * 
  1980.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  1981.  * or profits or other special, indirect and consequential damages, even if
  1982.  * Sun has been advised of the possibility of such damages.
  1983.  * 
  1984.  * Sun Microsystems, Inc.
  1985.  * 2550 Garcia Avenue
  1986.  * Mountain View, California  94043
  1987.  */
  1988. #ifndef lint
  1989. static char sccsid[] = "@(#)clnt_udp.c 1.5 85/03/17 Copyr 1984 Sun Micro";
  1990. #endif
  1991.  
  1992. /*
  1993.  * clnt_udp.c, Implements a UPD/IP based, client side RPC.
  1994.  *
  1995.  * Copyright (C) 1984, Sun Microsystems, Inc.
  1996.  */
  1997.  
  1998. #include <stdio.h>
  1999. #include "types.h"
  2000. #include <sys/socket.h>
  2001. #include <sys/time.h>
  2002. #include <netinet/in.h>
  2003. #include <netdb.h>
  2004. #include <errno.h>
  2005. #include "xdr.h"
  2006. #include "auth.h"
  2007. #include "clnt.h"
  2008. #include "rpc_msg.h"
  2009. #include "pmap_clnt.h"
  2010.  
  2011. char *malloc();
  2012. extern int errno;
  2013. long random();
  2014.  
  2015. /*
  2016.  * UDP bases client side rpc operations
  2017.  */
  2018. static enum clnt_stat    clntudp_call();
  2019. static void        clntudp_abort();
  2020. static void        clntudp_geterr();
  2021. static bool_t        clntudp_freeres();
  2022. static void        clntudp_destroy();
  2023.  
  2024. static struct clnt_ops udp_ops = {
  2025.     clntudp_call,
  2026.     clntudp_abort,
  2027.     clntudp_geterr,
  2028.     clntudp_freeres,
  2029.     clntudp_destroy
  2030. };
  2031.  
  2032. /* 
  2033.  * Private data kept per client handle
  2034.  */
  2035. struct cu_data {
  2036.     int           cu_sock;
  2037.     struct sockaddr_in cu_raddr;
  2038.     int           cu_rlen;
  2039.     struct timeval       cu_wait;
  2040.     struct rpc_err       cu_error;
  2041.     XDR           cu_outxdrs;
  2042.     u_int           cu_xdrpos;
  2043.     char           cu_outbuf[UDPMSGSIZE];
  2044.     char           cu_inbuf[UDPMSGSIZE];
  2045. };
  2046.  
  2047. /*
  2048.  * Create a UDP based client handle.
  2049.  * If *sockp<0, *sockp is set to a newly created UPD socket.
  2050.  * If raddr->sin_port is 0 a binder on the remote machine
  2051.  * is consulted for the correct port number.
  2052.  * NB: It is the clients responsibility to close *sockp.
  2053.  * NB: The rpch->cl_auth is initialized to null authentication.
  2054.  *     Caller may wish to set this something more useful.
  2055.  *
  2056.  * wait is the amount of time used between retransmitting a call if
  2057.  * no response has been heard;  retransmition occurs until the actual
  2058.  * rpc call times out.
  2059.  */
  2060. CLIENT *
  2061. clntudp_create(raddr, program, version, wait, sockp)
  2062.     struct sockaddr_in *raddr;
  2063.     u_long program;
  2064.     u_long version;
  2065.     struct timeval wait;
  2066.     register int *sockp;
  2067. {
  2068.     CLIENT *cl;
  2069.     register struct cu_data *cu;
  2070.     struct timeval now;
  2071.     struct rpc_msg call_msg;
  2072.  
  2073.     cl = (CLIENT *)mem_alloc(sizeof(CLIENT));
  2074.     if (cl == NULL) {
  2075.         fprintf(stderr, "clntudp_create: out of memory\n");
  2076.         rpc_createerr.cf_stat = RPC_SYSTEMERROR;
  2077.         rpc_createerr.cf_error.re_errno = errno;
  2078.         goto fooy;
  2079.     }
  2080.     cu = (struct cu_data *)mem_alloc(sizeof(*cu));
  2081.     if (cu == NULL) {
  2082.         fprintf(stderr, "clntudp_create: out of memory\n");
  2083.         rpc_createerr.cf_stat = RPC_SYSTEMERROR;
  2084.         rpc_createerr.cf_error.re_errno = errno;
  2085.         goto fooy;
  2086.     }
  2087.  
  2088.     (void)gettimeofday(&now, (struct timezone *)0);
  2089.     if (raddr->sin_port == 0) {
  2090.         u_short port;
  2091.         if ((port =
  2092.             pmap_getport(raddr, program, version, IPPROTO_UDP)) == 0) {
  2093.             goto fooy;
  2094.         }
  2095.         raddr->sin_port = htons(port);
  2096.     }
  2097.     cl->cl_ops = &udp_ops;
  2098.     cl->cl_private = (caddr_t)cu;
  2099.     cu->cu_raddr = *raddr;
  2100.     cu->cu_rlen = sizeof (cu->cu_raddr);
  2101.     cu->cu_wait = wait;
  2102.     call_msg.rm_xid = getpid() ^ (int)random() ^ now.tv_sec ^ now.tv_usec;
  2103.     call_msg.rm_direction = CALL;
  2104.     call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
  2105.     call_msg.rm_call.cb_prog = program;
  2106.     call_msg.rm_call.cb_vers = version;
  2107.     xdrmem_create(&(cu->cu_outxdrs), cu->cu_outbuf,
  2108.         UDPMSGSIZE, XDR_ENCODE);
  2109.     if (! xdr_callhdr(&(cu->cu_outxdrs), &call_msg)) {
  2110.         goto fooy;
  2111.     }
  2112.     cu->cu_xdrpos = XDR_GETPOS(&(cu->cu_outxdrs));
  2113.     cu->cu_sock = (*sockp < 0) ?
  2114.         (*sockp = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) :
  2115.         *sockp;
  2116.     if (cu->cu_sock < 0) {
  2117.         rpc_createerr.cf_stat = RPC_SYSTEMERROR;
  2118.         rpc_createerr.cf_error.re_errno = errno;
  2119.         goto fooy;
  2120.     }
  2121.     cl->cl_auth = authnone_create();
  2122.     return (cl);
  2123. fooy:
  2124.     mem_free((caddr_t)cu, sizeof(*cu));
  2125.     mem_free((caddr_t)cl, sizeof(CLIENT));
  2126.     return ((CLIENT *)NULL);
  2127. }
  2128.  
  2129. static enum clnt_stat 
  2130. clntudp_call(cl, proc, xargs, argsp, xresults, resultsp, timeout)
  2131.     register CLIENT    *cl;        /* client handle */
  2132.     u_long        proc;        /* procedure number */
  2133.     xdrproc_t    xargs;        /* xdr routine for args */
  2134.     caddr_t        argsp;        /* pointer to args */
  2135.     xdrproc_t    xresults;    /* xdr routine for results */
  2136.     caddr_t        resultsp;    /* pointer to results */
  2137.     struct timeval    timeout;    /* seconds to wait before giving up */
  2138. {
  2139.     register struct cu_data *cu = (struct cu_data *)cl->cl_private;
  2140.     register XDR *xdrs;
  2141.     register int outlen;
  2142.     register int inlen;
  2143.     int readfds, fromlen;
  2144.     register int mask;
  2145.     struct sockaddr_in from;
  2146.     struct rpc_msg reply_msg;
  2147.     XDR reply_xdrs;
  2148.     struct timeval time_waited;
  2149.     bool_t ok;
  2150.  
  2151. call_again:
  2152.     time_waited.tv_sec = 0;
  2153.     time_waited.tv_usec = 0;
  2154.     xdrs = &(cu->cu_outxdrs);
  2155.     xdrs->x_op = XDR_ENCODE;
  2156.     XDR_SETPOS(xdrs, cu->cu_xdrpos);
  2157.     /*
  2158.      * the transaction is the first thing in the out buffer
  2159.      */
  2160.     (*(u_short *)(cu->cu_outbuf))++;
  2161.     if ((! XDR_PUTLONG(xdrs, (long *)&proc)) ||
  2162.         (! AUTH_MARSHALL(cl->cl_auth, xdrs)) ||
  2163.         (! (*xargs)(xdrs, argsp)))
  2164.         return (cu->cu_error.re_status = RPC_CANTENCODEARGS);
  2165.     outlen = (int)XDR_GETPOS(xdrs);
  2166.     while (TRUE) {
  2167.  
  2168.         if (sendto(cu->cu_sock, cu->cu_outbuf, outlen, 0,
  2169.             (struct sockaddr *)&(cu->cu_raddr), cu->cu_rlen)
  2170.             != outlen) {
  2171.             cu->cu_error.re_errno = errno;
  2172.             return (cu->cu_error.re_status = RPC_CANTSEND);
  2173.         }
  2174.         /*
  2175.          * sub-optimal code appears inside the loop because we have
  2176.          * some clock time to spare while the packets are in flight.
  2177.          * (We assume that this is actually only executed once.)
  2178.          */
  2179.         reply_msg.acpted_rply.ar_verf = _null_auth;
  2180.         reply_msg.acpted_rply.ar_results.where = resultsp;
  2181.         reply_msg.acpted_rply.ar_results.proc = xresults;
  2182.         mask = 1 << cu->cu_sock;
  2183. rcv_again:
  2184.         readfds = mask;
  2185.         switch (select(32, &readfds, (int *)NULL, (int *)NULL,
  2186.             &(cu->cu_wait))) {
  2187.  
  2188.         case 0:
  2189.             time_waited.tv_sec += cu->cu_wait.tv_sec;
  2190.             time_waited.tv_usec += cu->cu_wait.tv_usec;
  2191.             while (time_waited.tv_usec >= 1000000) {
  2192.                 time_waited.tv_sec++;
  2193.                 time_waited.tv_usec -= 1000000;
  2194.             }
  2195.             if ((time_waited.tv_sec < timeout.tv_sec) ||
  2196.                 ((time_waited.tv_sec == timeout.tv_sec) &&
  2197.                 (time_waited.tv_usec < timeout.tv_usec)))
  2198.                 continue;
  2199.             return (cu->cu_error.re_status = RPC_TIMEDOUT);
  2200.  
  2201.         case -1:
  2202.             if (errno == EINTR)
  2203.                 goto rcv_again;
  2204.             cu->cu_error.re_errno = errno;
  2205.             return (cu->cu_error.re_status = RPC_CANTRECV);
  2206.         }
  2207.         if ((readfds & mask) == 0)
  2208.             goto rcv_again;
  2209. tryagain:
  2210.         fromlen = sizeof(struct sockaddr);
  2211.         inlen = recvfrom(cu->cu_sock, cu->cu_inbuf, UDPMSGSIZE, 0,
  2212.             (struct sockaddr *)&from, &fromlen);
  2213.         if (inlen < 0) {
  2214.             if (errno == EINTR)
  2215.                 goto tryagain;
  2216.             cu->cu_error.re_errno = errno;
  2217.             return (cu->cu_error.re_status = RPC_CANTRECV);
  2218.         }
  2219.         if (inlen < sizeof(u_long))
  2220.             goto rcv_again;
  2221.         /* see if reply transaction id matches sent id */
  2222.         if (*((u_long *)(cu->cu_inbuf)) != *((u_long *)(cu->cu_outbuf)))
  2223.             goto rcv_again;
  2224.         /* we now assume we have the proper reply */
  2225.         break;
  2226.     }
  2227.  
  2228.     /*
  2229.      * now decode and validate the response
  2230.      */
  2231.     xdrmem_create(&reply_xdrs, cu->cu_inbuf, (u_int)inlen, XDR_DECODE);
  2232.     ok = xdr_replymsg(&reply_xdrs, &reply_msg);
  2233.     /* XDR_DESTROY(&reply_xdrs);  save a few cycles on noop destroy */
  2234.     if (ok) {
  2235.         _seterr_reply(&reply_msg, &(cu->cu_error));
  2236.         if (cu->cu_error.re_status == RPC_SUCCESS) {
  2237.             if (! AUTH_VALIDATE(cl->cl_auth,
  2238.                 &reply_msg.acpted_rply.ar_verf)) {
  2239.                 cu->cu_error.re_status = RPC_AUTHERROR;
  2240.                 cu->cu_error.re_why = AUTH_INVALIDRESP;
  2241.             }
  2242.             if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) {
  2243.                 xdrs->x_op = XDR_FREE;
  2244.                 (void)xdr_opaque_auth(xdrs,
  2245.                     &(reply_msg.acpted_rply.ar_verf));
  2246.             } 
  2247.         }  /* end successful completion */
  2248.         else {
  2249.             /* maybe our credentials need to be refreshed ... */
  2250.             if (AUTH_REFRESH(cl->cl_auth))
  2251.                 goto call_again;
  2252.         }  /* end of unsuccessful completion */
  2253.     }  /* end of valid reply message */
  2254.     else {
  2255.         cu->cu_error.re_status = RPC_CANTDECODERES;
  2256.     }
  2257.     return (cu->cu_error.re_status);
  2258. }
  2259.  
  2260. static void
  2261. clntudp_geterr(cl, errp)
  2262.     CLIENT *cl;
  2263.     struct rpc_err *errp;
  2264. {
  2265.     register struct cu_data *cu = (struct cu_data *)cl->cl_private;
  2266.  
  2267.     *errp = cu->cu_error;
  2268. }
  2269.  
  2270.  
  2271. static bool_t
  2272. clntudp_freeres(cl, xdr_res, res_ptr)
  2273.     CLIENT *cl;
  2274.     xdrproc_t xdr_res;
  2275.     caddr_t res_ptr;
  2276. {
  2277.     register struct cu_data *cu = (struct cu_data *)cl->cl_private;
  2278.     register XDR *xdrs = &(cu->cu_outxdrs);
  2279.  
  2280.     xdrs->x_op = XDR_FREE;
  2281.     return ((*xdr_res)(xdrs, res_ptr));
  2282. }
  2283.  
  2284. static void 
  2285. clntudp_abort(/*h*/)
  2286.     /*CLIENT *h;*/
  2287. {
  2288. }
  2289.  
  2290. static void
  2291. clntudp_destroy(cl)
  2292.     CLIENT *cl;
  2293. {
  2294.     register struct cu_data *cu = (struct cu_data *)cl->cl_private;
  2295.  
  2296.     XDR_DESTROY(&(cu->cu_outxdrs));
  2297.     mem_free((caddr_t)cu, sizeof(*cu));
  2298.     mem_free((caddr_t)cl, sizeof(CLIENT));
  2299. }
  2300. !Funky!Stuff!
  2301.  
  2302. exit
  2303.