rsalz@bbn.com (Rich Salz) (03/03/88)
Submitted-by: Stephen X. Nahm <sxn@Sun.COM> Posting-number: Volume 13, Issue 81 Archive-name: rpc3.9/part04 #! /bin/sh # This is a shell archive. To extract, remove the header and type "sh filename" # cd rpc echo x - svc.h cat > svc.h <<'Funky_Stuff' /* @(#)svc.h 1.2 87/11/09 3.9 RPCSRC */ /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape * media and as a part of the software program in whole or part. Users * may copy or modify Sun RPC without charge, but are not authorized * to license or distribute it to anyone else except as part of a product or * program developed by the user. * * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. * * Sun RPC is provided with no support and without any obligation on the * part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC * OR ANY PART THEREOF. * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 */ /* @(#)svc.h 1.18 87/07/14 SMI * /* * svc.h, Server-side remote procedure call interface. * * Copyright (C) 1984, Sun Microsystems, Inc. */ #ifndef __SVC_HEADER__ #define __SVC_HEADER__ /* * This interface must manage two items concerning remote procedure calling: * * 1) An arbitrary number of transport connections upon which rpc requests * are received. The two most notable transports are TCP and UDP; they are * created and registered by routines in svc_tcp.c and svc_udp.c, respectively; * they in turn call xprt_register and xprt_unregister. * * 2) An arbitrary number of locally registered services. Services are * described by the following four data: program number, version number, * "service dispatch" function, a transport handle, and a boolean that * indicates whether or not the exported program should be registered with a * local binder service; if true the program's number and version and the * port number from the transport handle are registered with the binder. * These data are registered with the rpc svc system via svc_register. * * A service's dispatch function is called whenever an rpc request comes in * on a transport. The request's program and version numbers must match * those of the registered service. The dispatch function is passed two * parameters, struct svc_req * and SVCXPRT *, defined below. */ enum xprt_stat { XPRT_DIED, XPRT_MOREREQS, XPRT_IDLE }; /* * Server side transport handle */ typedef struct { int xp_sock; u_short xp_port; /* associated port number */ struct xp_ops { bool_t (*xp_recv)(); /* receive incomming requests */ enum xprt_stat (*xp_stat)(); /* get transport status */ bool_t (*xp_getargs)(); /* get arguments */ bool_t (*xp_reply)(); /* send reply */ bool_t (*xp_freeargs)();/* free mem allocated for args */ void (*xp_destroy)(); /* destroy this struct */ } *xp_ops; int xp_addrlen; /* length of remote address */ struct sockaddr_in xp_raddr; /* remote address */ struct opaque_auth xp_verf; /* raw response verifier */ caddr_t xp_p1; /* private */ caddr_t xp_p2; /* private */ } SVCXPRT; /* * Approved way of getting address of caller */ #define svc_getcaller(x) (&(x)->xp_raddr) /* * Operations defined on an SVCXPRT handle * * SVCXPRT *xprt; * struct rpc_msg *msg; * xdrproc_t xargs; * caddr_t argsp; */ #define SVC_RECV(xprt, msg) \ (*(xprt)->xp_ops->xp_recv)((xprt), (msg)) #define svc_recv(xprt, msg) \ (*(xprt)->xp_ops->xp_recv)((xprt), (msg)) #define SVC_STAT(xprt) \ (*(xprt)->xp_ops->xp_stat)(xprt) #define svc_stat(xprt) \ (*(xprt)->xp_ops->xp_stat)(xprt) #define SVC_GETARGS(xprt, xargs, argsp) \ (*(xprt)->xp_ops->xp_getargs)((xprt), (xargs), (argsp)) #define svc_getargs(xprt, xargs, argsp) \ (*(xprt)->xp_ops->xp_getargs)((xprt), (xargs), (argsp)) #define SVC_REPLY(xprt, msg) \ (*(xprt)->xp_ops->xp_reply) ((xprt), (msg)) #define svc_reply(xprt, msg) \ (*(xprt)->xp_ops->xp_reply) ((xprt), (msg)) #define SVC_FREEARGS(xprt, xargs, argsp) \ (*(xprt)->xp_ops->xp_freeargs)((xprt), (xargs), (argsp)) #define svc_freeargs(xprt, xargs, argsp) \ (*(xprt)->xp_ops->xp_freeargs)((xprt), (xargs), (argsp)) #define SVC_DESTROY(xprt) \ (*(xprt)->xp_ops->xp_destroy)(xprt) #define svc_destroy(xprt) \ (*(xprt)->xp_ops->xp_destroy)(xprt) /* * Service request */ struct svc_req { u_long rq_prog; /* service program number */ u_long rq_vers; /* service protocol version */ u_long rq_proc; /* the desired procedure */ struct opaque_auth rq_cred; /* raw creds from the wire */ caddr_t rq_clntcred; /* read only cooked cred */ SVCXPRT *rq_xprt; /* associated transport */ }; /* * Service registration * * svc_register(xprt, prog, vers, dispatch, protocol) * SVCXPRT *xprt; * u_long prog; * u_long vers; * void (*dispatch)(); * int protocol; /* like TCP or UDP, zero means do not register */ extern bool_t svc_register(); /* * Service un-registration * * svc_unregister(prog, vers) * u_long prog; * u_long vers; */ extern void svc_unregister(); /* * Transport registration. * * xprt_register(xprt) * SVCXPRT *xprt; */ extern void xprt_register(); /* * Transport un-register * * xprt_unregister(xprt) * SVCXPRT *xprt; */ extern void xprt_unregister(); /* * When the service routine is called, it must first check to see if it * knows about the procedure; if not, it should call svcerr_noproc * and return. If so, it should deserialize its arguments via * SVC_GETARGS (defined above). If the deserialization does not work, * svcerr_decode should be called followed by a return. Successful * decoding of the arguments should be followed the execution of the * procedure's code and a call to svc_sendreply. * * Also, if the service refuses to execute the procedure due to too- * weak authentication parameters, svcerr_weakauth should be called. * Note: do not confuse access-control failure with weak authentication! * * NB: In pure implementations of rpc, the caller always waits for a reply * msg. This message is sent when svc_sendreply is called. * Therefore pure service implementations should always call * svc_sendreply even if the function logically returns void; use * xdr.h - xdr_void for the xdr routine. HOWEVER, tcp based rpc allows * for the abuse of pure rpc via batched calling or pipelining. In the * case of a batched call, svc_sendreply should NOT be called since * this would send a return message, which is what batching tries to avoid. * It is the service/protocol writer's responsibility to know which calls are * batched and which are not. Warning: responding to batch calls may * deadlock the caller and server processes! */ extern bool_t svc_sendreply(); extern void svcerr_decode(); extern void svcerr_weakauth(); extern void svcerr_noproc(); /* * Lowest level dispatching -OR- who owns this process anyway. * Somebody has to wait for incoming requests and then call the correct * service routine. The routine svc_run does infinite waiting; i.e., * svc_run never returns. * Since another (co-existant) package may wish to selectively wait for * incoming calls or other events outside of the rpc architecture, the * routine svc_getreq is provided. It must be passed readfds, the * "in-place" results of a select system call (see select, section 2). */ /* * Global keeper of rpc service descriptors in use * dynamic; must be inspected before each call to select */ #ifdef FD_SETSIZE extern fd_set svc_fdset; #define svc_fds svc_fdset.fds_bits[0] /* compatibility */ #else extern int svc_fds; #endif /* def FD_SETSIZE */ /* * a small program implemented by the svc_rpc implementation itself; * also see clnt.h for protocol numbers. */ extern void rpctest_service(); extern void svc_getreq(); extern void svc_getreqset(); /* takes fdset instead of int */ extern void svc_run(); /* never returns */ /* * Socket to use on svcxxx_create call to get default socket */ #define RPC_ANYSOCK -1 /* * These are the existing service side transport implementations */ /* * Memory based rpc for testing and timing. */ extern SVCXPRT *svcraw_create(); /* * Udp based rpc. */ extern SVCXPRT *svcudp_create(); extern SVCXPRT *svcudp_bufcreate(); /* * Tcp based rpc. */ extern SVCXPRT *svctcp_create(); #endif !__SVC_HEADER__ Funky_Stuff len=`wc -c < svc.h` if [ $len != 8701 ] ; then echo error: svc.h was $len bytes long, should have been 8701 fi echo x - svc_auth.c cat > svc_auth.c <<'Funky_Stuff' /* @(#)svc_auth.c 1.1 87/11/04 3.9 RPCSRC */ /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape * media and as a part of the software program in whole or part. Users * may copy or modify Sun RPC without charge, but are not authorized * to license or distribute it to anyone else except as part of a product or * program developed by the user. * * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. * * Sun RPC is provided with no support and without any obligation on the * part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC * OR ANY PART THEREOF. * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 */ #if !defined(lint) && defined(SCCSIDS) static char sccsid[] = "@(#)svc_auth.c 1.19 87/08/11 Copyr 1984 Sun Micro"; #endif /* * svc_auth.c, Server-side rpc authenticator interface. * * Copyright (C) 1984, Sun Microsystems, Inc. */ #include <rpc/rpc.h> /* * svcauthsw is the bdevsw of server side authentication. * * Server side authenticators are called from authenticate by * using the client auth struct flavor field to index into svcauthsw. * The server auth flavors must implement a routine that looks * like: * * enum auth_stat * flavorx_auth(rqst, msg) * register struct svc_req *rqst; * register struct rpc_msg *msg; * */ enum auth_stat _svcauth_null(); /* no authentication */ enum auth_stat _svcauth_unix(); /* unix style (uid, gids) */ enum auth_stat _svcauth_short(); /* short hand unix style */ static struct { enum auth_stat (*authenticator)(); } svcauthsw[] = { _svcauth_null, /* AUTH_NULL */ _svcauth_unix, /* AUTH_UNIX */ _svcauth_short, /* AUTH_SHORT */ }; #define AUTH_MAX 2 /* HIGHEST AUTH NUMBER */ /* * The call rpc message, msg has been obtained from the wire. The msg contains * the raw form of credentials and verifiers. authenticate returns AUTH_OK * if the msg is successfully authenticated. If AUTH_OK then the routine also * does the following things: * set rqst->rq_xprt->verf to the appropriate response verifier; * sets rqst->rq_client_cred to the "cooked" form of the credentials. * * NB: rqst->rq_cxprt->verf must be pre-alloctaed; * its length is set appropriately. * * The caller still owns and is responsible for msg->u.cmb.cred and * msg->u.cmb.verf. The authentication system retains ownership of * rqst->rq_client_cred, the cooked credentials. * * There is an assumption that any flavour less than AUTH_NULL is * invalid. */ enum auth_stat _authenticate(rqst, msg) register struct svc_req *rqst; struct rpc_msg *msg; { register int cred_flavor; rqst->rq_cred = msg->rm_call.cb_cred; rqst->rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor; rqst->rq_xprt->xp_verf.oa_length = 0; cred_flavor = rqst->rq_cred.oa_flavor; if ((cred_flavor <= AUTH_MAX) && (cred_flavor >= AUTH_NULL)) { return ((*(svcauthsw[cred_flavor].authenticator))(rqst, msg)); } return (AUTH_REJECTEDCRED); } enum auth_stat _svcauth_null(/*rqst, msg*/) /*struct svc_req *rqst; struct rpc_msg *msg;*/ { return (AUTH_OK); } Funky_Stuff len=`wc -c < svc_auth.c` if [ $len != 3726 ] ; then echo error: svc_auth.c was $len bytes long, should have been 3726 fi echo x - svc_auth.h cat > svc_auth.h <<'Funky_Stuff' /* @(#)svc_auth.h 1.1 87/11/04 3.9 RPCSRC */ /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape * media and as a part of the software program in whole or part. Users * may copy or modify Sun RPC without charge, but are not authorized * to license or distribute it to anyone else except as part of a product or * program developed by the user. * * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. * * Sun RPC is provided with no support and without any obligation on the * part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC * OR ANY PART THEREOF. * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 */ /* @(#)svc_auth.h 1.6 86/07/16 SMI */ /* * svc_auth.h, Service side of rpc authentication. * * Copyright (C) 1984, Sun Microsystems, Inc. */ /* * Server side authenticator */ extern enum auth_stat _authenticate(); Funky_Stuff len=`wc -c < svc_auth.h` if [ $len != 1548 ] ; then echo error: svc_auth.h was $len bytes long, should have been 1548 fi echo x - svc_auth_unix.c cat > svc_auth_unix.c <<'Funky_Stuff' /* @(#)svc_auth_unix.c 1.1 87/11/04 3.9 RPCSRC */ /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape * media and as a part of the software program in whole or part. Users * may copy or modify Sun RPC without charge, but are not authorized * to license or distribute it to anyone else except as part of a product or * program developed by the user. * * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. * * Sun RPC is provided with no support and without any obligation on the * part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC * OR ANY PART THEREOF. * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 */ #if !defined(lint) && defined(SCCSIDS) static char sccsid[] = "@(#)svc_auth_unix.c 1.26 87/08/11 Copyr 1984 Sun Micro"; #endif /* * svc_auth_unix.c * Handles UNIX flavor authentication parameters on the service side of rpc. * There are two svc auth implementations here: AUTH_UNIX and AUTH_SHORT. * _svcauth_unix does full blown unix style uid,gid+gids auth, * _svcauth_short uses a shorthand auth to index into a cache of longhand auths. * Note: the shorthand has been gutted for efficiency. * * Copyright (C) 1984, Sun Microsystems, Inc. */ #include <stdio.h> #include <sys/time.h> #include <rpc/rpc.h> /* * Unix longhand authenticator */ enum auth_stat _svcauth_unix(rqst, msg) register struct svc_req *rqst; register struct rpc_msg *msg; { register enum auth_stat stat; XDR xdrs; register struct authunix_parms *aup; register long *buf; struct area { struct authunix_parms area_aup; char area_machname[MAX_MACHINE_NAME]; int area_gids[NGRPS]; } *area; u_int auth_len; int str_len, gid_len; register int i; area = (struct area *) rqst->rq_clntcred; aup = &area->area_aup; aup->aup_machname = area->area_machname; aup->aup_gids = area->area_gids; auth_len = (u_int)msg->rm_call.cb_cred.oa_length; xdrmem_create(&xdrs, msg->rm_call.cb_cred.oa_base, auth_len,XDR_DECODE); buf = XDR_INLINE(&xdrs, auth_len); if (buf != NULL) { aup->aup_time = IXDR_GET_LONG(buf); str_len = IXDR_GET_U_LONG(buf); bcopy((caddr_t)buf, aup->aup_machname, (u_int)str_len); aup->aup_machname[str_len] = 0; str_len = RNDUP(str_len); buf += str_len / sizeof (long); aup->aup_uid = IXDR_GET_LONG(buf); aup->aup_gid = IXDR_GET_LONG(buf); gid_len = IXDR_GET_U_LONG(buf); if (gid_len > NGRPS) { stat = AUTH_BADCRED; goto done; } aup->aup_len = gid_len; for (i = 0; i < gid_len; i++) { aup->aup_gids[i] = IXDR_GET_LONG(buf); } /* * five is the smallest unix credentials structure - * timestamp, hostname len (0), uid, gid, and gids len (0). */ if ((5 + gid_len) * BYTES_PER_XDR_UNIT + str_len > auth_len) { (void) printf("bad auth_len gid %d str %d auth %d\n", gid_len, str_len, auth_len); stat = AUTH_BADCRED; goto done; } } else if (! xdr_authunix_parms(&xdrs, aup)) { xdrs.x_op = XDR_FREE; (void)xdr_authunix_parms(&xdrs, aup); stat = AUTH_BADCRED; goto done; } rqst->rq_xprt->xp_verf.oa_flavor = AUTH_NULL; rqst->rq_xprt->xp_verf.oa_length = 0; stat = AUTH_OK; done: XDR_DESTROY(&xdrs); return (stat); } /* * Shorthand unix authenticator * Looks up longhand in a cache. */ /*ARGSUSED*/ enum auth_stat _svcauth_short(rqst, msg) struct svc_req *rqst; struct rpc_msg *msg; { return (AUTH_REJECTEDCRED); } Funky_Stuff len=`wc -c < svc_auth_unix.c` if [ $len != 4026 ] ; then echo error: svc_auth_unix.c was $len bytes long, should have been 4026 fi echo x - svc_raw.c cat > svc_raw.c <<'Funky_Stuff' /* @(#)svc_raw.c 1.1 87/11/04 3.9 RPCSRC */ /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape * media and as a part of the software program in whole or part. Users * may copy or modify Sun RPC without charge, but are not authorized * to license or distribute it to anyone else except as part of a product or * program developed by the user. * * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. * * Sun RPC is provided with no support and without any obligation on the * part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC * OR ANY PART THEREOF. * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 */ #if !defined(lint) && defined(SCCSIDS) static char sccsid[] = "@(#)svc_raw.c 1.15 87/08/11 Copyr 1984 Sun Micro"; #endif /* * svc_raw.c, This a toy for simple testing and timing. * Interface to create an rpc client and server in the same UNIX process. * This lets us similate rpc and get rpc (round trip) overhead, without * any interference from the kernal. * * Copyright (C) 1984, Sun Microsystems, Inc. */ #include <rpc/rpc.h> /* * This is the "network" that we will be moving data over */ static struct svcraw_private { char _raw_buf[UDPMSGSIZE]; SVCXPRT server; XDR xdr_stream; char verf_body[MAX_AUTH_BYTES]; } *svcraw_private; static bool_t svcraw_recv(); static enum xprt_stat svcraw_stat(); static bool_t svcraw_getargs(); static bool_t svcraw_reply(); static bool_t svcraw_freeargs(); static void svcraw_destroy(); static struct xp_ops server_ops = { svcraw_recv, svcraw_stat, svcraw_getargs, svcraw_reply, svcraw_freeargs, svcraw_destroy }; SVCXPRT * svcraw_create() { register struct svcraw_private *srp = svcraw_private; if (srp == 0) { srp = (struct svcraw_private *)calloc(1, sizeof (*srp)); if (srp == 0) return (0); } srp->server.xp_sock = 0; srp->server.xp_port = 0; srp->server.xp_ops = &server_ops; srp->server.xp_verf.oa_base = srp->verf_body; xdrmem_create(&srp->xdr_stream, srp->_raw_buf, UDPMSGSIZE, XDR_FREE); return (&srp->server); } static enum xprt_stat svcraw_stat() { return (XPRT_IDLE); } static bool_t svcraw_recv(xprt, msg) SVCXPRT *xprt; struct rpc_msg *msg; { register struct svcraw_private *srp = svcraw_private; register XDR *xdrs; if (srp == 0) return (0); xdrs = &srp->xdr_stream; xdrs->x_op = XDR_DECODE; XDR_SETPOS(xdrs, 0); if (! xdr_callmsg(xdrs, msg)) return (FALSE); return (TRUE); } static bool_t svcraw_reply(xprt, msg) SVCXPRT *xprt; struct rpc_msg *msg; { register struct svcraw_private *srp = svcraw_private; register XDR *xdrs; if (srp == 0) return (FALSE); xdrs = &srp->xdr_stream; xdrs->x_op = XDR_ENCODE; XDR_SETPOS(xdrs, 0); if (! xdr_replymsg(xdrs, msg)) return (FALSE); (void)XDR_GETPOS(xdrs); /* called just for overhead */ return (TRUE); } static bool_t svcraw_getargs(xprt, xdr_args, args_ptr) SVCXPRT *xprt; xdrproc_t xdr_args; caddr_t args_ptr; { register struct svcraw_private *srp = svcraw_private; if (srp == 0) return (FALSE); return ((*xdr_args)(&srp->xdr_stream, args_ptr)); } static bool_t svcraw_freeargs(xprt, xdr_args, args_ptr) SVCXPRT *xprt; xdrproc_t xdr_args; caddr_t args_ptr; { register struct svcraw_private *srp = svcraw_private; register XDR *xdrs; if (srp == 0) return (FALSE); xdrs = &srp->xdr_stream; xdrs->x_op = XDR_FREE; return ((*xdr_args)(xdrs, args_ptr)); } static void svcraw_destroy() { } Funky_Stuff len=`wc -c < svc_raw.c` if [ $len != 4120 ] ; then echo error: svc_raw.c was $len bytes long, should have been 4120 fi echo x - svc_run.c cat > svc_run.c <<'Funky_Stuff' /* @(#)svc_run.c 1.3 87/11/13 3.9 RPCSRC */ #if !defined(lint) && defined(SCCSIDS) static char sccsid[] = "@(#)svc_run.c 1.1 87/10/13 Copyr 1984 Sun Micro"; #endif /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape * media and as a part of the software program in whole or part. Users * may copy or modify Sun RPC without charge, but are not authorized * to license or distribute it to anyone else except as part of a product or * program developed by the user. * * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. * * Sun RPC is provided with no support and without any obligation on the * part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC * OR ANY PART THEREOF. * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 */ /* * This is the rpc server side idle loop * Wait for input, call server program. */ #include <rpc/rpc.h> #include <sys/errno.h> void svc_run() { #ifdef FD_SETSIZE fd_set readfds; #else int readfds; #endif /* def FD_SETSIZE */ extern int errno; for (;;) { #ifdef FD_SETSIZE readfds = svc_fdset; #else readfds = svc_fds; #endif /* def FD_SETSIZE */ switch (select(_rpc_dtablesize(), &readfds, (int *)0, (int *)0, (struct timeval *)0)) { case -1: if (errno == EINTR) { continue; } perror("svc_run: - select failed"); return; case 0: continue; default: svc_getreqset(&readfds); } } } Funky_Stuff len=`wc -c < svc_run.c` if [ $len != 2077 ] ; then echo error: svc_run.c was $len bytes long, should have been 2077 fi echo x - svc_simple.c cat > svc_simple.c <<'Funky_Stuff' /* @(#)svc_simple.c 1.1 87/11/04 3.9 RPCSRC */ /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape * media and as a part of the software program in whole or part. Users * may copy or modify Sun RPC without charge, but are not authorized * to license or distribute it to anyone else except as part of a product or * program developed by the user. * * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. * * Sun RPC is provided with no support and without any obligation on the * part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC * OR ANY PART THEREOF. * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 */ #if !defined(lint) && defined(SCCSIDS) static char sccsid[] = "@(#)svc_simple.c 1.18 87/08/11 Copyr 1984 Sun Micro"; #endif /* * svc_simple.c * Simplified front end to rpc. * * Copyright (C) 1984, Sun Microsystems, Inc. */ #include <stdio.h> #include <rpc/rpc.h> #include <sys/socket.h> #include <sys/time.h> #include <netdb.h> static struct proglst { char *(*p_progname)(); int p_prognum; int p_procnum; xdrproc_t p_inproc, p_outproc; struct proglst *p_nxt; } *proglst; static void universal(); static SVCXPRT *transp; struct proglst *pl; registerrpc(prognum, versnum, procnum, progname, inproc, outproc) char *(*progname)(); xdrproc_t inproc, outproc; { if (procnum == NULLPROC) { (void) fprintf(stderr, "can't reassign procedure number %d\n", NULLPROC); return (-1); } if (transp == 0) { transp = svcudp_create(RPC_ANYSOCK); if (transp == NULL) { (void) fprintf(stderr, "couldn't create an rpc server\n"); return (-1); } } (void) pmap_unset((u_long)prognum, (u_long)versnum); if (!svc_register(transp, (u_long)prognum, (u_long)versnum, universal, IPPROTO_UDP)) { (void) fprintf(stderr, "couldn't register prog %d vers %d\n", prognum, versnum); return (-1); } pl = (struct proglst *)malloc(sizeof(struct proglst)); if (pl == NULL) { (void) fprintf(stderr, "registerrpc: out of memory\n"); return (-1); } pl->p_progname = progname; pl->p_prognum = prognum; pl->p_procnum = procnum; pl->p_inproc = inproc; pl->p_outproc = outproc; pl->p_nxt = proglst; proglst = pl; return (0); } static void universal(rqstp, transp) struct svc_req *rqstp; SVCXPRT *transp; { int prog, proc; char *outdata; char xdrbuf[UDPMSGSIZE]; struct proglst *pl; /* * enforce "procnum 0 is echo" convention */ if (rqstp->rq_proc == NULLPROC) { if (svc_sendreply(transp, xdr_void, (char *)NULL) == FALSE) { (void) fprintf(stderr, "xxx\n"); exit(1); } return; } prog = rqstp->rq_prog; proc = rqstp->rq_proc; for (pl = proglst; pl != NULL; pl = pl->p_nxt) if (pl->p_prognum == prog && pl->p_procnum == proc) { /* decode arguments into a CLEAN buffer */ bzero(xdrbuf, sizeof(xdrbuf)); /* required ! */ if (!svc_getargs(transp, pl->p_inproc, xdrbuf)) { svcerr_decode(transp); return; } outdata = (*(pl->p_progname))(xdrbuf); if (outdata == NULL && pl->p_outproc != xdr_void) /* there was an error */ return; if (!svc_sendreply(transp, pl->p_outproc, outdata)) { (void) fprintf(stderr, "trouble replying to prog %d\n", pl->p_prognum); exit(1); } /* free the decoded arguments */ (void)svc_freeargs(transp, pl->p_inproc, xdrbuf); return; } (void) fprintf(stderr, "never registered prog %d\n", prog); exit(1); } Funky_Stuff len=`wc -c < svc_simple.c` if [ $len != 4088 ] ; then echo error: svc_simple.c was $len bytes long, should have been 4088 fi echo x - svc_tcp.c cat > svc_tcp.c <<'Funky_Stuff' /* @(#)svc_tcp.c 1.2 87/11/09 3.9 RPCSRC */ /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape * media and as a part of the software program in whole or part. Users * may copy or modify Sun RPC without charge, but are not authorized * to license or distribute it to anyone else except as part of a product or * program developed by the user. * * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. * * Sun RPC is provided with no support and without any obligation on the * part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC * OR ANY PART THEREOF. * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 */ #if !defined(lint) && defined(SCCSIDS) static char sccsid[] = "@(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro"; #endif /* * svc_tcp.c, Server side for TCP/IP based RPC. * * Copyright (C) 1984, Sun Microsystems, Inc. * * Actually implements two flavors of transporter - * a tcp rendezvouser (a listner and connection establisher) * and a record/tcp stream. */ #include <stdio.h> #include <rpc/rpc.h> #include <sys/socket.h> #include <sys/time.h> #include <errno.h> extern bool_t abort(); extern errno; /* * Ops vector for TCP/IP based rpc service handle */ static bool_t svctcp_recv(); static enum xprt_stat svctcp_stat(); static bool_t svctcp_getargs(); static bool_t svctcp_reply(); static bool_t svctcp_freeargs(); static void svctcp_destroy(); static struct xp_ops svctcp_op = { svctcp_recv, svctcp_stat, svctcp_getargs, svctcp_reply, svctcp_freeargs, svctcp_destroy }; /* * Ops vector for TCP/IP rendezvous handler */ static bool_t rendezvous_request(); static enum xprt_stat rendezvous_stat(); static struct xp_ops svctcp_rendezvous_op = { rendezvous_request, rendezvous_stat, abort, abort, abort, svctcp_destroy }; static int readtcp(), writetcp(); static SVCXPRT *makefd_xprt(); struct tcp_rendezvous { /* kept in xprt->xp_p1 */ u_int sendsize; u_int recvsize; }; struct tcp_conn { /* kept in xprt->xp_p1 */ enum xprt_stat strm_stat; u_long x_id; XDR xdrs; char verf_body[MAX_AUTH_BYTES]; }; /* * Usage: * xprt = svctcp_create(sock, send_buf_size, recv_buf_size); * * Creates, registers, and returns a (rpc) tcp based transporter. * Once *xprt is initialized, it is registered as a transporter * see (svc.h, xprt_register). This routine returns * a NULL if a problem occurred. * * If sock<0 then a socket is created, else sock is used. * If the socket, sock is not bound to a port then svctcp_create * binds it to an arbitrary port. The routine then starts a tcp * listener on the socket's associated port. In any (successful) case, * xprt->xp_sock is the registered socket number and xprt->xp_port is the * associated port number. * * Since tcp streams do buffered io similar to stdio, the caller can specify * how big the send and receive buffers are via the second and third parms; * 0 => use the system default. */ SVCXPRT * svctcp_create(sock, sendsize, recvsize) register int sock; u_int sendsize; u_int recvsize; { bool_t madesock = FALSE; register SVCXPRT *xprt; register struct tcp_rendezvous *r; struct sockaddr_in addr; int len = sizeof(struct sockaddr_in); if (sock == RPC_ANYSOCK) { if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { perror("svctcp_.c - udp socket creation problem"); return ((SVCXPRT *)NULL); } madesock = TRUE; } bzero((char *)&addr, sizeof (addr)); addr.sin_family = AF_INET; if (bindresvport(sock, &addr)) { addr.sin_port = 0; (void)bind(sock, (struct sockaddr *)&addr, len); } if ((getsockname(sock, (struct sockaddr *)&addr, &len) != 0) || (listen(sock, 2) != 0)) { perror("svctcp_.c - cannot getsockname or listen"); if (madesock) (void)close(sock); return ((SVCXPRT *)NULL); } r = (struct tcp_rendezvous *)mem_alloc(sizeof(*r)); if (r == NULL) { (void) fprintf(stderr, "svctcp_create: out of memory\n"); return (NULL); } r->sendsize = sendsize; r->recvsize = recvsize; xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT)); if (xprt == NULL) { (void) fprintf(stderr, "svctcp_create: out of memory\n"); return (NULL); } xprt->xp_p2 = NULL; xprt->xp_p1 = (caddr_t)r; xprt->xp_verf = _null_auth; xprt->xp_ops = &svctcp_rendezvous_op; xprt->xp_port = ntohs(addr.sin_port); xprt->xp_sock = sock; xprt_register(xprt); return (xprt); } /* * Like svtcp_create(), except the routine takes any *open* UNIX file * descriptor as its first input. */ SVCXPRT * svcfd_create(fd, sendsize, recvsize) int fd; u_int sendsize; u_int recvsize; { return (makefd_xprt(fd, sendsize, recvsize)); } static SVCXPRT * makefd_xprt(fd, sendsize, recvsize) int fd; u_int sendsize; u_int recvsize; { register SVCXPRT *xprt; register struct tcp_conn *cd; xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT)); if (xprt == (SVCXPRT *)NULL) { (void) fprintf(stderr, "svc_tcp: makefd_xprt: out of memory\n"); goto done; } cd = (struct tcp_conn *)mem_alloc(sizeof(struct tcp_conn)); if (cd == (struct tcp_conn *)NULL) { (void) fprintf(stderr, "svc_tcp: makefd_xprt: out of memory\n"); mem_free((char *) xprt, sizeof(SVCXPRT)); xprt = (SVCXPRT *)NULL; goto done; } cd->strm_stat = XPRT_IDLE; xdrrec_create(&(cd->xdrs), sendsize, recvsize, (caddr_t)xprt, readtcp, writetcp); xprt->xp_p2 = NULL; xprt->xp_p1 = (caddr_t)cd; xprt->xp_verf.oa_base = cd->verf_body; xprt->xp_addrlen = 0; xprt->xp_ops = &svctcp_op; /* truely deals with calls */ xprt->xp_port = 0; /* this is a connection, not a rendezvouser */ xprt->xp_sock = fd; xprt_register(xprt); done: return (xprt); } static bool_t rendezvous_request(xprt) register SVCXPRT *xprt; { int sock; struct tcp_rendezvous *r; struct sockaddr_in addr; int len; r = (struct tcp_rendezvous *)xprt->xp_p1; again: len = sizeof(struct sockaddr_in); if ((sock = accept(xprt->xp_sock, (struct sockaddr *)&addr, &len)) < 0) { if (errno == EINTR) goto again; return (FALSE); } /* * make a new transporter (re-uses xprt) */ xprt = makefd_xprt(sock, r->sendsize, r->recvsize); xprt->xp_raddr = addr; xprt->xp_addrlen = len; return (FALSE); /* there is never an rpc msg to be processed */ } static enum xprt_stat rendezvous_stat() { return (XPRT_IDLE); } static void svctcp_destroy(xprt) register SVCXPRT *xprt; { register struct tcp_conn *cd = (struct tcp_conn *)xprt->xp_p1; xprt_unregister(xprt); (void)close(xprt->xp_sock); if (xprt->xp_port != 0) { /* a rendezvouser socket */ xprt->xp_port = 0; } else { /* an actual connection socket */ XDR_DESTROY(&(cd->xdrs)); } mem_free((caddr_t)cd, sizeof(struct tcp_conn)); mem_free((caddr_t)xprt, sizeof(SVCXPRT)); } /* * All read operations timeout after 35 seconds. * A timeout is fatal for the connection. */ static struct timeval wait_per_try = { 35, 0 }; /* * reads data from the tcp conection. * any error is fatal and the connection is closed. * (And a read of zero bytes is a half closed stream => error.) */ static int readtcp(xprt, buf, len) register SVCXPRT *xprt; caddr_t buf; register int len; { register int sock = xprt->xp_sock; #ifdef FD_SETSIZE fd_set mask; fd_set readfds; FD_ZERO(&mask); FD_SET(sock, &mask); #else register int mask = 1 << sock; int readfds; #endif /* def FD_SETSIZE */ do { readfds = mask; if (select(_rpc_dtablesize(), &readfds, (int*)NULL, (int*)NULL, &wait_per_try) <= 0) { if (errno == EINTR) { continue; } goto fatal_err; } #ifdef FD_SETSIZE } while (!FD_ISSET(sock, &readfds)); #else } while (readfds != mask); #endif /* def FD_SETSIZE */ if ((len = read(sock, buf, len)) > 0) { return (len); } fatal_err: ((struct tcp_conn *)(xprt->xp_p1))->strm_stat = XPRT_DIED; return (-1); } /* * writes data to the tcp connection. * Any error is fatal and the connection is closed. */ static int writetcp(xprt, buf, len) register SVCXPRT *xprt; caddr_t buf; int len; { register int i, cnt; for (cnt = len; cnt > 0; cnt -= i, buf += i) { if ((i = write(xprt->xp_sock, buf, cnt)) < 0) { ((struct tcp_conn *)(xprt->xp_p1))->strm_stat = XPRT_DIED; return (-1); } } return (len); } static enum xprt_stat svctcp_stat(xprt) SVCXPRT *xprt; { register struct tcp_conn *cd = (struct tcp_conn *)(xprt->xp_p1); if (cd->strm_stat == XPRT_DIED) return (XPRT_DIED); if (! xdrrec_eof(&(cd->xdrs))) return (XPRT_MOREREQS); return (XPRT_IDLE); } static bool_t svctcp_recv(xprt, msg) SVCXPRT *xprt; register struct rpc_msg *msg; { register struct tcp_conn *cd = (struct tcp_conn *)(xprt->xp_p1); register XDR *xdrs = &(cd->xdrs); xdrs->x_op = XDR_DECODE; (void)xdrrec_skiprecord(xdrs); if (xdr_callmsg(xdrs, msg)) { cd->x_id = msg->rm_xid; return (TRUE); } return (FALSE); } static bool_t svctcp_getargs(xprt, xdr_args, args_ptr) SVCXPRT *xprt; xdrproc_t xdr_args; caddr_t args_ptr; { return ((*xdr_args)(&(((struct tcp_conn *)(xprt->xp_p1))->xdrs), args_ptr)); } static bool_t svctcp_freeargs(xprt, xdr_args, args_ptr) SVCXPRT *xprt; xdrproc_t xdr_args; caddr_t args_ptr; { register XDR *xdrs = &(((struct tcp_conn *)(xprt->xp_p1))->xdrs); xdrs->x_op = XDR_FREE; return ((*xdr_args)(xdrs, args_ptr)); } static bool_t svctcp_reply(xprt, msg) SVCXPRT *xprt; register struct rpc_msg *msg; { register struct tcp_conn *cd = (struct tcp_conn *)(xprt->xp_p1); register XDR *xdrs = &(cd->xdrs); register bool_t stat; xdrs->x_op = XDR_ENCODE; msg->rm_xid = cd->x_id; stat = xdr_replymsg(xdrs, msg); (void)xdrrec_endofrecord(xdrs, TRUE); return (stat); } Funky_Stuff len=`wc -c < svc_tcp.c` if [ $len != 10278 ] ; then echo error: svc_tcp.c was $len bytes long, should have been 10278 fi echo x - svc_udp.c cat > svc_udp.c <<'Funky_Stuff' /* @(#)svc_udp.c 1.1 87/11/04 3.9 RPCSRC */ /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape * media and as a part of the software program in whole or part. Users * may copy or modify Sun RPC without charge, but are not authorized * to license or distribute it to anyone else except as part of a product or * program developed by the user. * * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. * * Sun RPC is provided with no support and without any obligation on the * part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC * OR ANY PART THEREOF. * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 */ #if !defined(lint) && defined(SCCSIDS) static char sccsid[] = "@(#)svc_udp.c 1.21 87/08/11 Copyr 1984 Sun Micro"; #endif /* * svc_udp.c, * Server side for UDP/IP based RPC. (Does some caching in the hopes of * achieving execute-at-most-once semantics.) * * Copyright (C) 1984, Sun Microsystems, Inc. */ #include <stdio.h> #include <rpc/rpc.h> #include <sys/socket.h> #include <errno.h> #define rpc_buffer(xprt) ((xprt)->xp_p1) #define MAX(a, b) ((a > b) ? a : b) static bool_t svcudp_recv(); static bool_t svcudp_reply(); static enum xprt_stat svcudp_stat(); static bool_t svcudp_getargs(); static bool_t svcudp_freeargs(); static void svcudp_destroy(); static struct xp_ops svcudp_op = { svcudp_recv, svcudp_stat, svcudp_getargs, svcudp_reply, svcudp_freeargs, svcudp_destroy }; extern int errno; /* * kept in xprt->xp_p2 */ struct svcudp_data { u_int su_iosz; /* byte size of send.recv buffer */ u_long su_xid; /* transaction id */ XDR su_xdrs; /* XDR handle */ char su_verfbody[MAX_AUTH_BYTES]; /* verifier body */ char * su_cache; /* cached data, NULL if no cache */ }; #define su_data(xprt) ((struct svcudp_data *)(xprt->xp_p2)) /* * Usage: * xprt = svcudp_create(sock); * * If sock<0 then a socket is created, else sock is used. * If the socket, sock is not bound to a port then svcudp_create * binds it to an arbitrary port. In any (successful) case, * xprt->xp_sock is the registered socket number and xprt->xp_port is the * associated port number. * Once *xprt is initialized, it is registered as a transporter; * see (svc.h, xprt_register). * The routines returns NULL if a problem occurred. */ SVCXPRT * svcudp_bufcreate(sock, sendsz, recvsz) register int sock; u_int sendsz, recvsz; { bool_t madesock = FALSE; register SVCXPRT *xprt; register struct svcudp_data *su; struct sockaddr_in addr; int len = sizeof(struct sockaddr_in); if (sock == RPC_ANYSOCK) { if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { perror("svcudp_create: socket creation problem"); return ((SVCXPRT *)NULL); } madesock = TRUE; } bzero((char *)&addr, sizeof (addr)); addr.sin_family = AF_INET; if (bindresvport(sock, &addr)) { addr.sin_port = 0; (void)bind(sock, (struct sockaddr *)&addr, len); } if (getsockname(sock, (struct sockaddr *)&addr, &len) != 0) { perror("svcudp_create - cannot getsockname"); if (madesock) (void)close(sock); return ((SVCXPRT *)NULL); } xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT)); if (xprt == NULL) { (void)fprintf(stderr, "svcudp_create: out of memory\n"); return (NULL); } su = (struct svcudp_data *)mem_alloc(sizeof(*su)); if (su == NULL) { (void)fprintf(stderr, "svcudp_create: out of memory\n"); return (NULL); } su->su_iosz = ((MAX(sendsz, recvsz) + 3) / 4) * 4; if ((rpc_buffer(xprt) = mem_alloc(su->su_iosz)) == NULL) { (void)fprintf(stderr, "svcudp_create: out of memory\n"); return (NULL); } xdrmem_create( &(su->su_xdrs), rpc_buffer(xprt), su->su_iosz, XDR_DECODE); su->su_cache = NULL; xprt->xp_p2 = (caddr_t)su; xprt->xp_verf.oa_base = su->su_verfbody; xprt->xp_ops = &svcudp_op; xprt->xp_port = ntohs(addr.sin_port); xprt->xp_sock = sock; xprt_register(xprt); return (xprt); } SVCXPRT * svcudp_create(sock) int sock; { return(svcudp_bufcreate(sock, UDPMSGSIZE, UDPMSGSIZE)); } static enum xprt_stat svcudp_stat(xprt) SVCXPRT *xprt; { return (XPRT_IDLE); } static bool_t svcudp_recv(xprt, msg) register SVCXPRT *xprt; struct rpc_msg *msg; { register struct svcudp_data *su = su_data(xprt); register XDR *xdrs = &(su->su_xdrs); register int rlen; char *reply; u_long replylen; again: xprt->xp_addrlen = sizeof(struct sockaddr_in); rlen = recvfrom(xprt->xp_sock, rpc_buffer(xprt), (int) su->su_iosz, 0, (struct sockaddr *)&(xprt->xp_raddr), &(xprt->xp_addrlen)); if (rlen == -1 && errno == EINTR) goto again; if (rlen < 4*sizeof(u_long)) return (FALSE); xdrs->x_op = XDR_DECODE; XDR_SETPOS(xdrs, 0); if (! xdr_callmsg(xdrs, msg)) return (FALSE); su->su_xid = msg->rm_xid; if (su->su_cache != NULL) { if (cache_get(xprt, msg, &reply, &replylen)) { (void) sendto(xprt->xp_sock, reply, (int) replylen, 0, (struct sockaddr *) &xprt->xp_raddr, (int) &xprt->xp_addrlen); return(FALSE); } } return (TRUE); } static bool_t svcudp_reply(xprt, msg) register SVCXPRT *xprt; struct rpc_msg *msg; { register struct svcudp_data *su = su_data(xprt); register XDR *xdrs = &(su->su_xdrs); register int slen; register bool_t stat = FALSE; xdrs->x_op = XDR_ENCODE; XDR_SETPOS(xdrs, 0); msg->rm_xid = su->su_xid; if (xdr_replymsg(xdrs, msg)) { slen = (int)XDR_GETPOS(xdrs); if (sendto(xprt->xp_sock, rpc_buffer(xprt), slen, 0, (struct sockaddr *)&(xprt->xp_raddr), xprt->xp_addrlen) == slen) { stat = TRUE; if (su->su_cache && slen >= 0) { cache_set(xprt, (u_long) slen); } } } return (stat); } static bool_t svcudp_getargs(xprt, xdr_args, args_ptr) SVCXPRT *xprt; xdrproc_t xdr_args; caddr_t args_ptr; { return ((*xdr_args)(&(su_data(xprt)->su_xdrs), args_ptr)); } static bool_t svcudp_freeargs(xprt, xdr_args, args_ptr) SVCXPRT *xprt; xdrproc_t xdr_args; caddr_t args_ptr; { register XDR *xdrs = &(su_data(xprt)->su_xdrs); xdrs->x_op = XDR_FREE; return ((*xdr_args)(xdrs, args_ptr)); } static void svcudp_destroy(xprt) register SVCXPRT *xprt; { register struct svcudp_data *su = su_data(xprt); xprt_unregister(xprt); (void)close(xprt->xp_sock); XDR_DESTROY(&(su->su_xdrs)); mem_free(rpc_buffer(xprt), su->su_iosz); mem_free((caddr_t)su, sizeof(struct svcudp_data)); mem_free((caddr_t)xprt, sizeof(SVCXPRT)); } /***********this could be a separate file*********************/ /* * Fifo cache for udp server * Copies pointers to reply buffers into fifo cache * Buffers are sent again if retransmissions are detected. */ #define SPARSENESS 4 /* 75% sparse */ #define CACHE_PERROR(msg) \ (void) fprintf(stderr,"%s\n", msg) #define ALLOC(type, size) \ (type *) mem_alloc((unsigned) (sizeof(type) * (size))) #define BZERO(addr, type, size) \ bzero((char *) addr, sizeof(type) * (int) (size)) /* * An entry in the cache */ typedef struct cache_node *cache_ptr; struct cache_node { /* * Index into cache is xid, proc, vers, prog and address */ u_long cache_xid; u_long cache_proc; u_long cache_vers; u_long cache_prog; struct sockaddr_in cache_addr; /* * The cached reply and length */ char * cache_reply; u_long cache_replylen; /* * Next node on the list, if there is a collision */ cache_ptr cache_next; }; /* * The entire cache */ struct udp_cache { u_long uc_size; /* size of cache */ cache_ptr *uc_entries; /* hash table of entries in cache */ cache_ptr *uc_fifo; /* fifo list of entries in cache */ u_long uc_nextvictim; /* points to next victim in fifo list */ u_long uc_prog; /* saved program number */ u_long uc_vers; /* saved version number */ u_long uc_proc; /* saved procedure number */ struct sockaddr_in uc_addr; /* saved caller's address */ }; /* * the hashing function */ #define CACHE_LOC(transp, xid) \ (xid % (SPARSENESS*((struct udp_cache *) su_data(transp)->su_cache)->uc_size)) /* * Enable use of the cache. * Note: there is no disable. */ svcudp_enablecache(transp, size) SVCXPRT *transp; u_long size; { struct svcudp_data *su = su_data(transp); struct udp_cache *uc; if (su->su_cache != NULL) { CACHE_PERROR("enablecache: cache already enabled"); return(0); } uc = ALLOC(struct udp_cache, 1); if (uc == NULL) { CACHE_PERROR("enablecache: could not allocate cache"); return(0); } uc->uc_size = size; uc->uc_nextvictim = 0; uc->uc_entries = ALLOC(cache_ptr, size * SPARSENESS); if (uc->uc_entries == NULL) { CACHE_PERROR("enablecache: could not allocate cache data"); return(0); } BZERO(uc->uc_entries, cache_ptr, size * SPARSENESS); uc->uc_fifo = ALLOC(cache_ptr, size); if (uc->uc_fifo == NULL) { CACHE_PERROR("enablecache: could not allocate cache fifo"); return(0); } BZERO(uc->uc_fifo, cache_ptr, size); su->su_cache = (char *) uc; return(1); } /* * Set an entry in the cache */ static cache_set(xprt, replylen) SVCXPRT *xprt; u_long replylen; { register cache_ptr victim; register cache_ptr *vicp; register struct svcudp_data *su = su_data(xprt); struct udp_cache *uc = (struct udp_cache *) su->su_cache; u_int loc; char *newbuf; /* * Find space for the new entry, either by * reusing an old entry, or by mallocing a new one */ victim = uc->uc_fifo[uc->uc_nextvictim]; if (victim != NULL) { loc = CACHE_LOC(xprt, victim->cache_xid); for (vicp = &uc->uc_entries[loc]; *vicp != NULL && *vicp != victim; vicp = &(*vicp)->cache_next) ; if (*vicp == NULL) { CACHE_PERROR("cache_set: victim not found"); return; } *vicp = victim->cache_next; /* remote from cache */ newbuf = victim->cache_reply; } else { victim = ALLOC(struct cache_node, 1); if (victim == NULL) { CACHE_PERROR("cache_set: victim alloc failed"); return; } newbuf = mem_alloc(su->su_iosz); if (newbuf == NULL) { CACHE_PERROR("cache_set: could not allocate new rpc_buffer"); return; } } /* * Store it away */ victim->cache_replylen = replylen; victim->cache_reply = rpc_buffer(xprt); rpc_buffer(xprt) = newbuf; xdrmem_create(&(su->su_xdrs), rpc_buffer(xprt), su->su_iosz, XDR_ENCODE); victim->cache_xid = su->su_xid; victim->cache_proc = uc->uc_proc; victim->cache_vers = uc->uc_vers; victim->cache_prog = uc->uc_prog; victim->cache_addr = uc->uc_addr; loc = CACHE_LOC(xprt, victim->cache_xid); victim->cache_next = uc->uc_entries[loc]; uc->uc_entries[loc] = victim; uc->uc_fifo[uc->uc_nextvictim++] = victim; uc->uc_nextvictim %= uc->uc_size; } /* * Try to get an entry from the cache * return 1 if found, 0 if not found */ static cache_get(xprt, msg, replyp, replylenp) SVCXPRT *xprt; struct rpc_msg *msg; char **replyp; u_long *replylenp; { u_int loc; register cache_ptr ent; register struct svcudp_data *su = su_data(xprt); register struct udp_cache *uc = (struct udp_cache *) su->su_cache; # define EQADDR(a1, a2) (bcmp((char*)&a1, (char*)&a2, sizeof(a1)) == 0) loc = CACHE_LOC(xprt, su->su_xid); for (ent = uc->uc_entries[loc]; ent != NULL; ent = ent->cache_next) { if (ent->cache_xid == su->su_xid && ent->cache_proc == uc->uc_proc && ent->cache_vers == uc->uc_vers && ent->cache_prog == uc->uc_prog && EQADDR(ent->cache_addr, uc->uc_addr)) { *replyp = ent->cache_reply; *replylenp = ent->cache_replylen; return(1); } } /* * Failed to find entry * Remember a few things so we can do a set later */ uc->uc_proc = msg->rm_call.cb_proc; uc->uc_vers = msg->rm_call.cb_vers; uc->uc_prog = msg->rm_call.cb_prog; uc->uc_addr = xprt->xp_raddr; return(0); } Funky_Stuff len=`wc -c < svc_udp.c` if [ $len != 12207 ] ; then echo error: svc_udp.c was $len bytes long, should have been 12207 fi echo x - types.h cat > types.h <<'Funky_Stuff' /* @(#)types.h 1.2 87/11/07 3.9 RPCSRC */ /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape * media and as a part of the software program in whole or part. Users * may copy or modify Sun RPC without charge, but are not authorized * to license or distribute it to anyone else except as part of a product or * program developed by the user. * * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. * * Sun RPC is provided with no support and without any obligation on the * part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC * OR ANY PART THEREOF. * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 */ /* @(#)types.h 1.18 87/07/24 SMI */ /* * Rpc additions to <sys/types.h> */ #ifndef __TYPES_RPC_HEADER__ #define __TYPES_RPC_HEADER__ #define bool_t int #define enum_t int #define FALSE (0) #define TRUE (1) #define __dontcare__ -1 #ifndef NULL # define NULL 0 #endif extern char *malloc(); #define mem_alloc(bsize) malloc(bsize) #define mem_free(ptr, bsize) free(ptr) #ifndef makedev /* ie, we haven't already included it */ #include <sys/types.h> #endif /*#include <sys/time.h>*/ #endif /* ndef __TYPES_RPC_HEADER__ */ Funky_Stuff len=`wc -c < types.h` if [ $len != 1847 ] ; then echo error: types.h was $len bytes long, should have been 1847 fi cd .. echo more files to follow exit -- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.