sources-request@genrad.UUCP (04/16/85)
From: blyon@sun (Bob Lyon) ----------------- cut here -------------------- # run this script through "sh" to extract files echo x - auth.h sed 's/^X//' >auth.h <<'!Funky!Stuff!' /* * 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 */ /* @(#)auth.h 1.3 85/03/28 SMI */ /* * auth.h, Authentication interface. * Copyright (C) 1984, Sun Microsystems, Inc. * * The data structures are completely opaque to the client. The client * is required to pass a AUTH * to routines that create rpc * "sessions". */ #define MAX_AUTH_BYTES 400 /* * Status returned from authentication check */ enum auth_stat { AUTH_OK=0, /* * failed at remote end */ AUTH_BADCRED=1, /* bogus credentials (seal broken) */ AUTH_REJECTEDCRED=2, /* client should begin new session */ AUTH_BADVERF=3, /* bogus verifier (seal broken) */ AUTH_REJECTEDVERF=4, /* verifier expired or was replayed */ AUTH_TOOWEAK=5, /* rejected due to security reasons */ /* * failed locally */ AUTH_INVALIDRESP=6, /* bogus response verifier */ AUTH_FAILED=7 /* some unknown reason */ }; union des_block { struct { u_long high; u_long low; } key; char c[8]; }; /* * Authentication info. Opaque to client. */ struct opaque_auth { enum_t oa_flavor; /* flavor of auth */ caddr_t oa_base; /* address of more auth stuff */ u_int oa_length; /* not to exceed MAX_AUTH_BYTES */ }; /* * Auth handle, interface to client side authenticators. */ typedef struct { struct opaque_auth ah_cred; struct opaque_auth ah_verf; union des_block ah_key; struct auth_ops { void (*ah_nextverf)(); int (*ah_marshal)(); /* nextverf & serialize */ int (*ah_validate)(); /* validate varifier */ int (*ah_refresh)(); /* refresh credentials */ void (*ah_destroy)(); /* destroy this structure */ } *ah_ops; caddr_t ah_private; } AUTH; /* * Authentication ops. * The ops and the auth handle provide the interface to the authenticators. * * AUTH *auth; * XDR *xdrs; * struct opaque_auth verf; */ #define AUTH_NEXTVERF(auth) \ ((*((auth)->ah_ops->ah_nextverf))(auth)) #define auth_nextverf(auth) \ ((*((auth)->ah_ops->ah_nextverf))(auth)) #define AUTH_MARSHALL(auth, xdrs) \ ((*((auth)->ah_ops->ah_marshal))(auth, xdrs)) #define auth_marshall(auth, xdrs) \ ((*((auth)->ah_ops->ah_marshal))(auth, xdrs)) #define AUTH_VALIDATE(auth, verfp) \ ((*((auth)->ah_ops->ah_validate))((auth), verfp)) #define auth_validate(auth, verfp) \ ((*((auth)->ah_ops->ah_validate))((auth), verfp)) #define AUTH_REFRESH(auth) \ ((*((auth)->ah_ops->ah_refresh))(auth)) #define auth_refresh(auth) \ ((*((auth)->ah_ops->ah_refresh))(auth)) #define AUTH_DESTROY(auth) \ ((*((auth)->ah_ops->ah_destroy))(auth)) #define auth_destroy(auth) \ ((*((auth)->ah_ops->ah_destroy))(auth)) extern struct opaque_auth _null_auth; /* * These are the various implementations of client side authenticators. */ /* * Null authentication */ extern AUTH *authnone_create(); /* takes no parameters */ #define AUTH_NULL 0 /* * Unix style authentication * AUTH *authunix_create(machname, uid, gid, len, aup_gids) * char *machname; * int uid; * int gid; * int len; * int *aup_gids; */ extern AUTH *authunix_create(); extern AUTH *authunix_create_default(); /* takes no parameters */ #define AUTH_UNIX 1 /* unix style (uid, gids) */ #define AUTH_SHORT 2 /* short hand unix style */ !Funky!Stuff! echo x - auth_none.c sed 's/^X//' >auth_none.c <<'!Funky!Stuff!' /* * 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 */ #ifndef lint static char sccsid[] = "@(#)auth_none.c 1.4 85/03/17 Copyr 1984 Sun Micro"; #endif /* * auth_none.c * Creates a client authentication handle for passing "null" * credentials and verifiers to remote systems. * * Copyright (C) 1984, Sun Microsystems, Inc. */ #include "types.h" #include "xdr.h" #include "auth.h" #define NULL ((caddr_t)0) #define MAX_MARSHEL_SIZE 20 /* * Authenticator operations routines */ static void authnone_verf(); static void authnone_destroy(); static bool_t authnone_marshal(); static bool_t authnone_validate(); static bool_t authnone_refresh(); static struct auth_ops ops = { authnone_verf, authnone_marshal, authnone_validate, authnone_refresh, authnone_destroy }; static AUTH no_client; static char marshalled_client[MAX_MARSHEL_SIZE]; static u_int mcnt = 0; AUTH * authnone_create() { XDR xdr_stream; register XDR *xdrs; if (! mcnt) { no_client.ah_cred = no_client.ah_verf = _null_auth; no_client.ah_ops = &ops; xdrs = &xdr_stream; xdrmem_create(xdrs, marshalled_client, (u_int)MAX_MARSHEL_SIZE, XDR_ENCODE); if ((! xdr_opaque_auth(xdrs, &no_client.ah_cred)) || (! xdr_opaque_auth(xdrs, &no_client.ah_verf))) { } else { mcnt = XDR_GETPOS(xdrs); } XDR_DESTROY(xdrs); } return (&no_client); } static bool_t /* ARGSUSED */ authnone_marshal(client, xdrs) AUTH *client; XDR *xdrs; { return ((*xdrs->x_ops->x_putbytes)(xdrs, marshalled_client, mcnt)); } static void authnone_verf() { } static bool_t authnone_validate() { return (TRUE); } static bool_t authnone_refresh() { return (FALSE); } static void authnone_destroy() { } !Funky!Stuff! echo x - auth_unix.c sed 's/^X//' >auth_unix.c <<'!Funky!Stuff!' /* * 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 */ #ifndef lint static char sccsid[] = "@(#)auth_unix.c 1.5 85/03/17 Copyr 1984 Sun Micro"; #endif /* * auth_unix.c, Implements UNIX style authentication parameters. * * Copyright (C) 1984, Sun Microsystems, Inc. * * The system is very weak. The client uses no encryption for it's * credentials and only sends null verifiers. The server sends backs * null verifiers or optionally a verifier that suggests a new short hand * for the credentials. * */ #include <stdio.h> #include "types.h" #include <sys/time.h> #include "xdr.h" #include "auth.h" #include "auth_unix.h" char *malloc(); /* * Unix authenticator operations vector */ static void authunix_nextverf(); static bool_t authunix_marshal(); static bool_t authunix_validate(); static bool_t authunix_refresh(); static void authunix_destroy(); static struct auth_ops auth_unix_ops = { authunix_nextverf, authunix_marshal, authunix_validate, authunix_refresh, authunix_destroy }; /* * This struct is pointed to by the ah_private field of an auth_handle. */ struct audata { struct opaque_auth au_origcred; /* original credentials */ struct opaque_auth au_shcred; /* short hand cred */ u_long au_shfaults; /* short hand cache faults */ char au_marshed[MAX_AUTH_BYTES]; u_int au_mpos; /* xdr pos at end of marshed */ }; #define AUTH_PRIVATE(auth) ((struct audata *)auth->ah_private) static bool_t marshal_new_auth(); /* * Create a unix style authenticator. * Returns an auth handle with the given stuff in it. */ AUTH * authunix_create(machname, uid, gid, len, aup_gids) char *machname; int uid; int gid; register int len; int *aup_gids; { struct authunix_parms aup; char mymem[MAX_AUTH_BYTES]; struct timeval now; XDR xdrs; register AUTH *auth; register struct audata *au; /* * Allocate and set up auth handle */ auth = (AUTH *)mem_alloc(sizeof(*auth)); if (auth == NULL) { fprintf(stderr, "authunix_create: out of memory\n"); return (NULL); } au = (struct audata *)mem_alloc(sizeof(*au)); if (au == NULL) { fprintf(stderr, "authunix_create: out of memory\n"); return (NULL); } auth->ah_ops = &auth_unix_ops; auth->ah_private = (caddr_t)au; auth->ah_verf = au->au_shcred = _null_auth; au->au_shfaults = 0; /* * fill in param struct from the given params */ (void)gettimeofday(&now, (struct timezone *)0); aup.aup_time = now.tv_sec; aup.aup_machname = machname; aup.aup_uid = uid; aup.aup_gid = gid; aup.aup_len = (u_int)len; aup.aup_gids = aup_gids; /* * Serialize the parameters into origcred */ xdrmem_create(&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE); if (! xdr_authunix_parms(&xdrs, &aup)) abort(); au->au_origcred.oa_length = len = XDR_GETPOS(&xdrs); au->au_origcred.oa_flavor = AUTH_UNIX; if ((au->au_origcred.oa_base = mem_alloc(len)) == NULL) { fprintf(stderr, "authunix_create: out of memory\n"); return (NULL); } bcopy(mymem, au->au_origcred.oa_base, (u_int)len); /* * set auth handle to reflect new cred. */ auth->ah_cred = au->au_origcred; marshal_new_auth(auth); return (auth); } /* * Returns an auth handle with parameters determined by doing lots of * syscalls. */ AUTH * authunix_create_default() { register int len; char machname[MAX_MACHINE_NAME + 1]; register int uid; register int gid; int gids[NGRPS]; if (gethostname(machname, MAX_MACHINE_NAME) == -1) abort(); machname[MAX_MACHINE_NAME] = 0; uid = geteuid(); gid = getegid(); if ((len = getgroups(NGRPS, gids)) < 0) abort(); return (authunix_create(machname, uid, gid, len, gids)); } /* * authunix operations */ static void authunix_nextverf(auth) AUTH *auth; { /* no action necessary */ } static bool_t authunix_marshal(auth, xdrs) AUTH *auth; XDR *xdrs; { register struct audata *au = AUTH_PRIVATE(auth); return (XDR_PUTBYTES(xdrs, au->au_marshed, au->au_mpos)); } static bool_t authunix_validate(auth, verf) register AUTH *auth; struct opaque_auth verf; { register struct audata *au; XDR xdrs; if (verf.oa_flavor == AUTH_SHORT) { au = AUTH_PRIVATE(auth); xdrmem_create(&xdrs, verf.oa_base, verf.oa_length, XDR_DECODE); if (au->au_shcred.oa_base != NULL) { mem_free(au->au_shcred.oa_base, au->au_shcred.oa_length); au->au_shcred.oa_base = NULL; } if (xdr_opaque_auth(&xdrs, &au->au_shcred)) { auth->ah_cred = au->au_shcred; } else { xdrs.x_op = XDR_FREE; (void)xdr_opaque_auth(&xdrs, &au->au_shcred); au->au_shcred.oa_base = NULL; auth->ah_cred = au->au_origcred; } marshal_new_auth(auth); } return (TRUE); } static bool_t authunix_refresh(auth) register AUTH *auth; { register struct audata *au = AUTH_PRIVATE(auth); struct authunix_parms aup; struct timeval now; XDR xdrs; register int stat; if (auth->ah_cred.oa_base == au->au_origcred.oa_base) { /* there is no hope. Punt */ return (FALSE); } au->au_shfaults ++; /* first deserialize the creds back into a struct authunix_parms */ aup.aup_machname = NULL; aup.aup_gids = (int *)NULL; xdrmem_create(&xdrs, au->au_origcred.oa_base, au->au_origcred.oa_length, XDR_DECODE); stat = xdr_authunix_parms(&xdrs, &aup); if (! stat) goto done; /* update the time and serialize in place */ (void)gettimeofday(&now, (struct timezone *)0); aup.aup_time = now.tv_sec; xdrs.x_op = XDR_ENCODE; XDR_SETPOS(&xdrs, 0); stat = xdr_authunix_parms(&xdrs, &aup); if (! stat) goto done; auth->ah_cred = au->au_origcred; marshal_new_auth(auth); done: /* free the struct authunix_parms created by deserializing */ xdrs.x_op = XDR_FREE; (void)xdr_authunix_parms(&xdrs, &aup); XDR_DESTROY(&xdrs); return (stat); } static void authunix_destroy(auth) register AUTH *auth; { register struct audata *au = AUTH_PRIVATE(auth); mem_free(au->au_origcred.oa_base, au->au_origcred.oa_length); if (au->au_shcred.oa_base != NULL) mem_free(au->au_shcred.oa_base, au->au_shcred.oa_length); mem_free(auth->ah_private, sizeof(struct audata)); if (auth->ah_verf.oa_base != NULL) mem_free(auth->ah_verf.oa_base, auth->ah_verf.oa_length); mem_free((caddr_t)auth, sizeof(*auth)); } /* * Marshals (pre-serializes) an auth struct. * sets private data, au_marshed and au_mpos */ static bool_t marshal_new_auth(auth) register AUTH *auth; { XDR xdr_stream; register XDR *xdrs = &xdr_stream; register struct audata *au = AUTH_PRIVATE(auth); xdrmem_create(xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE); if ((! xdr_opaque_auth(xdrs, &(auth->ah_cred))) || (! xdr_opaque_auth(xdrs, &(auth->ah_verf)))) { } else { au->au_mpos = XDR_GETPOS(xdrs); } XDR_DESTROY(xdrs); } !Funky!Stuff! echo x - auth_unix.h sed 's/^X//' >auth_unix.h <<'!Funky!Stuff!' /* * 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 */ /* @(#)auth_unix.h 1.1 84/12/20 SMI */ /* * auth_unix.h, Protocol for UNIX style authentication parameters for RPC * * Copyright (C) 1984, Sun Microsystems, Inc. */ /* * The system is very weak. The client uses no encryption for it * credentials and only sends null verifiers. The server sends backs * null verifiers or optionally a verifier that suggests a new short hand * for the credentials. */ /* The machine name is part of a credential; it may not exceed 255 bytes */ #define MAX_MACHINE_NAME 255 /* gids compose part of a credential; there may not be more than 10 of them */ #define NGRPS 8 /* * Unix style credentials. */ struct authunix_parms { u_long aup_time; char *aup_machname; int aup_uid; int aup_gid; u_int aup_len; int *aup_gids; }; extern bool_t xdr_authunix_parms(); /* * If a response verifier has flavor AUTH_SHORT, * then the body of the response verifier encapsulates the following structure; * again it is serialized in the obvious fashion. */ struct short_hand_verf { struct opaque_auth new_cred; }; !Funky!Stuff! echo x - authunix_prot.c sed 's/^X//' >authunix_prot.c <<'!Funky!Stuff!' /* * 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 */ #ifndef lint static char sccsid[] = "@(#)authunix_prot.c 1.3 85/03/12 Copyr 1984 Sun Micro"; #endif /* * authunix_prot.c * XDR for UNIX style authentication parameters for RPC * * Copyright (C) 1984, Sun Microsystems, Inc. */ #include "types.h" #include "xdr.h" #include "auth.h" #include "auth_unix.h" /* * XDR for unix authentication parameters. */ bool_t xdr_authunix_parms(xdrs, p) register XDR *xdrs; register struct authunix_parms *p; { int i; if (xdr_u_long(xdrs, &(p->aup_time)) && xdr_string(xdrs, &(p->aup_machname), MAX_MACHINE_NAME) && xdr_int(xdrs, &(p->aup_uid)) && xdr_int(xdrs, &(p->aup_gid)) && xdr_array(xdrs, (caddr_t *)&(p->aup_gids), &(p->aup_len), NGRPS, sizeof(int), xdr_int) ) { return (TRUE); } return (FALSE); } !Funky!Stuff! echo x - clnt.h sed 's/^X//' >clnt.h <<'!Funky!Stuff!' /* * 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 */ /* @(#)clnt.h 1.3 85/03/20 SMI */ /* * clnt.h - Client side remote procedure call interface. * * Copyright (C) 1984, Sun Microsystems, Inc. */ /* * Rpc calls return an enum clnt_stat. This should be looked at more, * since each implementation is required to live with this (implementation * independent) list of errors. */ enum clnt_stat { RPC_SUCCESS=0, /* call succeeded */ /* * local errors */ RPC_CANTENCODEARGS=1, /* can't encode arguments */ RPC_CANTDECODERES=2, /* can't decode results */ RPC_CANTSEND=3, /* failure in sending call */ RPC_CANTRECV=4, /* failure in receiving result */ RPC_TIMEDOUT=5, /* call timed out */ /* * remote errors */ RPC_VERSMISMATCH=6, /* rpc versions not compatible */ RPC_AUTHERROR=7, /* authentication error */ RPC_PROGUNAVAIL=8, /* program not available */ RPC_PROGVERSMISMATCH=9, /* program version mismatched */ RPC_PROCUNAVAIL=10, /* procedure unavailable */ RPC_CANTDECODEARGS=11, /* decode arguments error */ RPC_SYSTEMERROR=12, /* generic "other problem" */ /* * callrpc errors */ RPC_UNKNOWNHOST=13, /* unknown host name */ /* * _ create errors */ RPC_PMAPFAILURE=14, /* the pmapper failed in its call */ RPC_PROGNOTREGISTERED=15, /* remote program is not registered */ /* * unspecified error */ RPC_FAILED=16 }; /* * Error info. */ struct rpc_err { enum clnt_stat re_status; union { int RE_errno; /* realated system error */ enum auth_stat RE_why; /* why the auth error occurred */ struct { u_long low; /* lowest verion supported */ u_long high; /* highest verion supported */ } RE_vers; struct { /* maybe meaningful if RPC_FAILED */ long s1; long s2; } RE_lb; /* life boot & debugging only */ } ru; #define re_errno ru.RE_errno #define re_why ru.RE_why #define re_vers ru.RE_vers #define re_lb ru.RE_lb }; /* * Client rpc handle. * Created by individual implementations, see e.g. rpc_udp.c. * Client is responsible for initializing auth, see e.g. auth_none.c. */ typedef struct { AUTH *cl_auth; /* authenticator */ struct clnt_ops { enum clnt_stat (*cl_call)(); /* call remote procedure */ void (*cl_abort)(); /* abort a call */ void (*cl_geterr)(); /* get specific error code */ bool_t (*cl_freeres)(); /* frees results */ void (*cl_destroy)();/* destroy this structure */ } *cl_ops; caddr_t cl_private; /* private stuff */ } CLIENT; /* * client side rpc interface ops * * Parameter types are: * */ /* * enum clnt_stat * CLNT_CALL(rh, proc, xargs, argsp, xres, resp, timeout) * CLIENT *rh; * u_long proc; * xdrproc_t xargs; * caddr_t argsp; * xdrproc_t xres; * caddr_t resp; * struct timeval timeout; */ #define CLNT_CALL(rh, proc, xargs, argsp, xres, resp, secs) \ ((*(rh)->cl_ops->cl_call)(rh, proc, xargs, argsp, xres, resp, secs)) #define clnt_call(rh, proc, xargs, argsp, xres, resp, secs) \ ((*(rh)->cl_ops->cl_call)(rh, proc, xargs, argsp, xres, resp, secs)) /* * void * CLNT_ABORT(rh); * CLIENT *rh; */ #define CLNT_ABORT(rh) ((*(rh)->cl_ops->cl_abort)(rh)) #define clnt_abort(rh) ((*(rh)->cl_ops->cl_abort)(rh)) /* * struct rpc_err * CLNT_GETERR(rh); * CLIENT *rh; */ #define CLNT_GETERR(rh,errp) ((*(rh)->cl_ops->cl_geterr)(rh, errp)) #define clnt_geterr(rh,errp) ((*(rh)->cl_ops->cl_geterr)(rh, errp)) /* * bool_t * CLNT_FREERES(rh, xres, resp); * CLIENT *rh; * xdrproc_t xres; * caddr_t resp; */ #define CLNT_FREERES(rh,xres,resp) ((*(rh)->cl_ops->cl_freeres)(rh,xres,resp)) #define clnt_freeres(rh,xres,resp) ((*(rh)->cl_ops->cl_freeres)(rh,xres,resp)) /* * void * CLNT_DESTROY(rh); * CLIENT *rh; */ #define CLNT_DESTROY(rh) ((*(rh)->cl_ops->cl_destroy)(rh)) #define clnt_destroy(rh) ((*(rh)->cl_ops->cl_destroy)(rh)) /* * RPCTEST is a test program which is accessable on every rpc * transport/port. It is used for testing, performance evaluation, * and network administration. */ #define RPCTEST_PROGRAM ((u_long)1) #define RPCTEST_VERSION ((u_long)1) #define RPCTEST_NULL_PROC ((u_long)2) #define RPCTEST_NULL_BATCH_PROC ((u_long)3) /* * By convention, procedure 0 takes null arguments and returns them */ #define NULLPROC ((u_long)0) /* * Below are the client handle creation routines for the various * implementations of client side rpc. They can return NULL if a * creation failure occurs. */ /* * Memory based rpc (for speed check and testing) * CLIENT * * clntraw_create(prog, vers) * u_long prog; * u_long vers; */ extern CLIENT *clntraw_create(); /* * UDP based rpc. * CLIENT * * clntudp_create(raddr, program, version, wait, sockp) * struct sockaddr_in *raddr; * u_long program; * u_long version; * struct timeval wait; * int *sockp; */ extern CLIENT *clntudp_create(); #define UDPMSGSIZE 8800 /* * TCP based rpc * CLIENT * * clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz) * struct sockaddr_in *raddr; * u_long prog; * u_long version; * register int *sockp; * u_int sendsz; * u_int recvsz; */ extern CLIENT *clnttcp_create(); /* * If a creation fails, the following allows the user to figure out why. */ struct rpc_createerr { enum clnt_stat cf_stat; struct rpc_err cf_error; /* useful when cf_stat == RPC_PMAPFAILURE */ }; extern struct rpc_createerr rpc_createerr; !Funky!Stuff! echo x - clnt_perror.c sed 's/^X//' >clnt_perror.c <<'!Funky!Stuff!' /* * 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 */ #ifndef lint static char sccsid[] = "@(#)clnt_perror.c 1.1 85/02/08 Copyr 1984 Sun Micro"; #endif /* * clnt_perror.c * * Copyright (C) 1984, Sun Microsystems, Inc. * */ #include "types.h" #include "xdr.h" #include "auth.h" #include "clnt.h" #include "rpc_msg.h" #include <stdio.h> extern char *sys_errlist[]; /* * Print reply error info */ void clnt_perror(rpch, s) CLIENT *rpch; char *s; { struct rpc_err e; void clnt_perrno(); CLNT_GETERR(rpch, &e); fprintf(stderr, "%s: ", s); switch (e.re_status) { case RPC_SUCCESS: case RPC_CANTENCODEARGS: case RPC_CANTDECODERES: case RPC_TIMEDOUT: case RPC_PROGUNAVAIL: case RPC_PROCUNAVAIL: case RPC_CANTDECODEARGS: clnt_perrno(e.re_status); break; case RPC_CANTSEND: clnt_perrno(e.re_status); fprintf(stderr, "; errno = %s", sys_errlist[e.re_errno]); break; case RPC_CANTRECV: clnt_perrno(e.re_status); fprintf(stderr, "; errno = %s", sys_errlist[e.re_errno]); break; case RPC_VERSMISMATCH: clnt_perrno(e.re_status); fprintf(stderr, "; low version = %lu, high version = %lu", e.re_vers.low, e.re_vers.high); break; case RPC_AUTHERROR: clnt_perrno(e.re_status); fprintf(stderr, "; why = "); switch (e.re_why) { case AUTH_OK: fprintf(stderr, "AUTH_OK"); break; case AUTH_BADCRED: fprintf(stderr, "AUTH_BOGUS_CREDENTIAL"); break; case AUTH_REJECTEDCRED: fprintf(stderr, "AUTH_REJECTED_CREDENTIAL"); break; case AUTH_BADVERF: fprintf(stderr, "AUTH_BOGUS_VERIFIER"); break; case AUTH_REJECTEDVERF: fprintf(stderr, "AUTH_REJECTED_VERIFIER"); break; case AUTH_TOOWEAK: fprintf(stderr, "AUTH_TOO_WEAK (remote error)"); break; case AUTH_INVALIDRESP: fprintf(stderr, "AUTH_INVALID_RESPONSE"); break; default: fprintf(stderr, "AUTH_UNKNOWN_FAILURE"); break; } break; case RPC_PROGVERSMISMATCH: clnt_perrno(e.re_status); fprintf(stderr, "; low version = %lu, high version = %lu", e.re_vers.low, e.re_vers.high); break; default: fprintf(stderr, "RPC_UNKNOWN_FAILURE; s1 = %lu, s2 = %lu", e.re_lb.s1, e.re_lb.s2); break; } fprintf(stderr, "\n"); } /* * This interface for use by clntrpc */ void clnt_perrno(num) enum clnt_stat num; { switch (num) { case RPC_SUCCESS: fprintf(stderr, "RPC_SUCCESS"); break; case RPC_CANTENCODEARGS: fprintf(stderr, "RPC_CANT_ENCODE_ARGS"); break; case RPC_CANTDECODERES: fprintf(stderr, "RPC_CANT_DECODE_RESULTS"); break; case RPC_CANTSEND: fprintf(stderr, "RPC_CANT_SEND"); break; case RPC_CANTRECV: fprintf(stderr, "RPC_CANT_RECV"); break; case RPC_TIMEDOUT: fprintf(stderr, "RPC_TIMED_OUT"); break; case RPC_VERSMISMATCH: fprintf(stderr, "RPC_VERSION_MISMATCH"); break; case RPC_AUTHERROR: fprintf(stderr, "RPC_AUTH_ERROR"); break; case RPC_PROGUNAVAIL: fprintf(stderr, "RPC_REMOTE_PROGRAM_UNAVAILABLE"); break; case RPC_PROGVERSMISMATCH: fprintf(stderr, "RPC_PROGRAM_MISMATCH"); break; case RPC_PROCUNAVAIL: fprintf(stderr, "RPC_UNKNOWN_PROCEDURE"); break; case RPC_CANTDECODEARGS: fprintf(stderr, "RPC_CANT_DECODE_ARGS"); break; case RPC_UNKNOWNHOST: fprintf(stderr, "RPC_UNKNOWNHOST"); break; case RPC_PMAPFAILURE: fprintf(stderr, "RPC_PMAP_FAILURE"); break; case RPC_PROGNOTREGISTERED: fprintf(stderr, "RPC_PROG_NOT_REGISTERED"); break; case RPC_SYSTEMERROR: fprintf(stderr, "RPC_SYSTEM_ERROR"); break; } } /* * A handle on why an rpc creation routine failed (returned NULL.) */ struct rpc_createerr rpc_createerr; clnt_pcreateerror(s) char *s; { fprintf(stderr, "%s: ", s); clnt_perrno(rpc_createerr.cf_stat); switch (rpc_createerr.cf_stat) { case RPC_PMAPFAILURE: fprintf(stderr, " - "); clnt_perrno(rpc_createerr.cf_error.re_status); break; case RPC_SYSTEMERROR: fprintf(stderr, " - %s", sys_errlist[rpc_createerr.cf_error.re_errno]); break; } fprintf(stderr, "\n"); } !Funky!Stuff! echo x - clnt_raw.c sed 's/^X//' >clnt_raw.c <<'!Funky!Stuff!' /* * 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 */ #ifndef lint static char sccsid[] = "@(#)clnt_raw.c 1.4 85/03/17 Copyr 1984 Sun Micro"; #endif /* * clnt_raw.c * * Copyright (C) 1984, Sun Microsystems, Inc. * * Memory based rpc for simple testing and timing. * Interface to create an rpc client and server in the same process. * This lets us similate rpc and get round trip overhead, without * any interference from the kernal. */ #include "types.h" #include <sys/time.h> #include <netinet/in.h> #include "xdr.h" #include "auth.h" #include "clnt.h" #include "rpc_msg.h" #define NULL ((caddr_t)0) #define MCALL_MSG_SIZE 24 /* * This is the "network" we will be moving stuff over. */ char _raw_buf[UDPMSGSIZE]; static char mashl_callmsg[MCALL_MSG_SIZE]; static u_int mcnt; static enum clnt_stat clntraw_call(); static void clntraw_abort(); static void clntraw_geterr(); static bool_t clntraw_freeres(); static void clntraw_destroy(); static struct clnt_ops client_ops = { clntraw_call, clntraw_abort, clntraw_geterr, clntraw_freeres, clntraw_destroy }; static CLIENT client_object; static CLIENT *client = &client_object; static XDR xdr_stream; void svc_getreq(); /* * Create a client handle for memory based rpc. */ CLIENT * clntraw_create(prog, vers) u_long prog; u_long vers; { struct rpc_msg call_msg; XDR *xdrs = &xdr_stream; /* * pre-serialize the staic part of the call msg and stash it away */ call_msg.rm_direction = CALL; call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; call_msg.rm_call.cb_prog = prog; call_msg.rm_call.cb_vers = vers; xdrmem_create(xdrs, mashl_callmsg, MCALL_MSG_SIZE, XDR_ENCODE); if (! xdr_callhdr(xdrs, &call_msg)) { perror("clnt_raw.c - Fatal header serialization error."); } mcnt = XDR_GETPOS(xdrs); XDR_DESTROY(xdrs); /* * Set xdrmem for client/server shared buffer */ xdrmem_create(xdrs, _raw_buf, UDPMSGSIZE, XDR_FREE); /* * create client handle */ client->cl_ops = &client_ops; client->cl_auth = authnone_create(); return (client); } static enum clnt_stat clntraw_call(h, proc, xargs, argsp, xresults, resultsp, timeout) CLIENT *h; u_long proc; xdrproc_t xargs; caddr_t argsp; xdrproc_t xresults; caddr_t resultsp; struct timeval timeout; { register XDR *xdrs = &xdr_stream; struct rpc_msg msg; enum clnt_stat status; struct rpc_err error; call_again: /* * send request */ xdrs->x_op = XDR_ENCODE; XDR_SETPOS(xdrs, 0); ((struct rpc_msg *)mashl_callmsg)->rm_xid ++ ; if ((! XDR_PUTBYTES(xdrs, mashl_callmsg, mcnt)) || (! XDR_PUTLONG(xdrs, (long *)&proc)) || (! AUTH_MARSHALL(h->cl_auth, xdrs)) || (! (*xargs)(xdrs, argsp))) { return (RPC_CANTENCODEARGS); } (void)XDR_GETPOS(xdrs); /* called just to cause overhead */ /* * We have to call server input routine here because this is * all going on in one process. Yuk. */ svc_getreq(1); /* * get results */ xdrs->x_op = XDR_DECODE; XDR_SETPOS(xdrs, 0); msg.acpted_rply.ar_verf = _null_auth; msg.acpted_rply.ar_results.where = resultsp; msg.acpted_rply.ar_results.proc = xresults; if (! xdr_replymsg(xdrs, &msg)) return (RPC_CANTDECODERES); _seterr_reply(&msg, &error); status = error.re_status; if (status == RPC_SUCCESS) { if (! AUTH_VALIDATE(h->cl_auth, &msg.acpted_rply.ar_verf)) { status = RPC_AUTHERROR; } } /* end successful completion */ else { if (AUTH_REFRESH(h->cl_auth)) goto call_again; } /* end of unsuccessful completion */ if (status == RPC_SUCCESS) { if (! AUTH_VALIDATE(h->cl_auth, &msg.acpted_rply.ar_verf)) { status = RPC_AUTHERROR; } if (msg.acpted_rply.ar_verf.oa_base != NULL) { xdrs->x_op = XDR_FREE; (void)xdr_opaque_auth(xdrs, &(msg.acpted_rply.ar_verf)); } } return (status); } static void clntraw_geterr() { } static bool_t clntraw_freeres(cl, xdr_res, res_ptr) CLIENT *cl; xdrproc_t xdr_res; caddr_t res_ptr; { register XDR *xdrs = &xdr_stream; xdrs->x_op = XDR_FREE; return ((*xdr_res)(xdrs, res_ptr)); } static void clntraw_abort() { } static void clntraw_destroy() { } !Funky!Stuff! echo x - clnt_simple.c sed 's/^X//' >clnt_simple.c <<'!Funky!Stuff!' /* * 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 */ #ifndef lint static char sccsid[] = "@(#)clnt_simple.c 1.1 84/12/20 Copyr 1984 Sun Micro"; #endif /* * clnt_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> callrpc(host, prognum, versnum, procnum, inproc, in, outproc, out) char *host; xdrproc_t inproc, outproc; char *in, *out; { struct sockaddr_in server_addr; enum clnt_stat clnt_stat; struct hostent *hp; struct timeval timeout, tottimeout; static CLIENT *client; static int socket = RPC_ANYSOCK; static int oldprognum, oldversnum, valid; static char oldhost[256]; if (valid && oldprognum == prognum && oldversnum == versnum && strcmp(oldhost, host) == 0) { /* reuse old client */ } else { close(socket); socket = RPC_ANYSOCK; if (client) { clnt_destroy(client); client = NULL; } if ((hp = gethostbyname(host)) == NULL) return ((int) RPC_UNKNOWNHOST); timeout.tv_usec = 0; timeout.tv_sec = 10; bcopy(hp->h_addr, &server_addr.sin_addr, hp->h_length); server_addr.sin_family = AF_INET; server_addr.sin_port = 0; if ((client = clntudp_create(&server_addr, prognum, versnum, timeout, &socket)) == NULL) return ((int) rpc_createerr.cf_stat); valid = 1; oldprognum = prognum; oldversnum = versnum; strcpy(oldhost, host); } tottimeout.tv_sec = 25; tottimeout.tv_usec = 0; clnt_stat = clnt_call(client, procnum, inproc, in, outproc, out, tottimeout); /* * if call failed, empty cache */ if (clnt_stat != RPC_SUCCESS) valid = 0; return ((int) clnt_stat); } !Funky!Stuff! echo x - clnt_tcp.c sed 's/^X//' >clnt_tcp.c <<'!Funky!Stuff!' /* * 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 */ #ifndef lint static char sccsid[] = "@(#)clnt_tcp.c 1.5 85/03/17 Copyr 1984 Sun Micro"; #endif /* * clnt_tcp.c, Implements a TCP/IP based, client side RPC. * * Copyright (C) 1984, Sun Microsystems, Inc. * * TCP based RPC supports 'batched calls'. * A sequence of calls may be batched-up in a send buffer. The rpc call * return immediately to the client even though the call was not necessarily * sent. The batching occurs iff the results' xdr routine is NULL (0) AND * the rpc timeout value is zero (see clnt.h, rpc). * * Clients should NOT casually batch calls that in fact return results; that is, * the server side should be aware that a call is batched and not produce any * return message. Batched calls that produce many result messages can * deadlock (netlock) the client and the server.... * * Now go hang yourself. */ #include <stdio.h> #include "types.h" #include <sys/socket.h> #include <sys/time.h> #include <netinet/in.h> #include <netdb.h> #include <errno.h> #include "xdr.h" #include "auth.h" #include "clnt.h" #include "rpc_msg.h" #include "pmap_clnt.h" #define MCALL_MSG_SIZE 24 char *malloc(); extern int errno; long random(); static int readtcp(); static int writetcp(); static enum clnt_stat clnttcp_call(); static void clnttcp_abort(); static void clnttcp_geterr(); static bool_t clnttcp_freeres(); static void clnttcp_destroy(); static struct clnt_ops tcp_ops = { clnttcp_call, clnttcp_abort, clnttcp_geterr, clnttcp_freeres, clnttcp_destroy }; struct ct_data { int ct_sock; struct timeval ct_wait; struct rpc_err ct_error; char ct_mcall[MCALL_MSG_SIZE]; /* marshalled callmsg */ u_int ct_mpos; /* pos after marshal */ XDR ct_xdrs; }; /* * Create a client handle for a tcp/ip connection. * If *sockp<0, *sockp is set to a newly created TCP socket and it is * connected to raddr. If *sockp non-negative then * raddr is ignored. The rpc/tcp package does buffering * similar to stdio, so the client must pick send and receive buffer sizes,]; * 0 => use the default. * If raddr->sin_port is 0, then a binder on the remote machine is * consulted for the right port number. * NB: *sockp is copied into a private area. * NB: It is the clients responsibility to close *sockp. * NB: The rpch->cl_auth is set null authentication. Caller may wish to set this * something more useful. */ CLIENT * clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz) struct sockaddr_in *raddr; u_long prog; u_long vers; register int *sockp; u_int sendsz; u_int recvsz; { CLIENT *h; register struct ct_data *ct; struct timeval now; struct rpc_msg call_msg; h = (CLIENT *)mem_alloc(sizeof(*h)); if (h == NULL) { fprintf(stderr, "clnttcp_create: out of memory\n"); rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; goto fooy; } ct = (struct ct_data *)mem_alloc(sizeof(*ct)); if (ct == NULL) { fprintf(stderr, "clnttcp_create: out of memory\n"); rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; goto fooy; } /* * If no port number given ask the pmap for one */ if (raddr->sin_port == 0) { u_short port; if ((port = pmap_getport(raddr, prog, vers, IPPROTO_TCP)) == 0) { mem_free((caddr_t)ct, sizeof(struct ct_data)); mem_free((caddr_t)h, sizeof(CLIENT)); return ((CLIENT *)NULL); } raddr->sin_port = htons(port); } /* * If no socket given, open one */ if (*sockp < 0) { if (((*sockp = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) || (connect(*sockp, (struct sockaddr *)raddr, sizeof(*raddr)) < 0)) { rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; goto fooy; } } /* * Set up private data struct */ ct->ct_sock = *sockp; ct->ct_wait.tv_usec = 0; /* * Initialize call message */ (void)gettimeofday(&now, (struct timezone *)0); call_msg.rm_xid = getpid() ^ (int)random() ^ now.tv_sec ^ now.tv_usec; call_msg.rm_direction = CALL; call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; call_msg.rm_call.cb_prog = prog; call_msg.rm_call.cb_vers = vers; /* * pre-serialize the staic part of the call msg and stash it away */ xdrmem_create(&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE, XDR_ENCODE); if (! xdr_callhdr(&(ct->ct_xdrs), &call_msg)) { goto fooy; } ct->ct_mpos = XDR_GETPOS(&(ct->ct_xdrs)); XDR_DESTROY(&(ct->ct_xdrs)); /* * Create a client handle which uses xdrrec for serialization * and authnone for authentication. */ xdrrec_create(&(ct->ct_xdrs), sendsz, recvsz, (caddr_t)ct, readtcp, writetcp); h->cl_ops = &tcp_ops; h->cl_private = (caddr_t) ct; h->cl_auth = authnone_create(); return (h); fooy: /* * Something goofed, free stuff and barf */ mem_free((caddr_t)ct, sizeof(struct ct_data)); mem_free((caddr_t)h, sizeof(CLIENT)); (void)close(*sockp); return ((CLIENT *)NULL); } static enum clnt_stat clnttcp_call(h, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout) register CLIENT *h; u_long proc; xdrproc_t xdr_args; caddr_t args_ptr; xdrproc_t xdr_results; caddr_t results_ptr; struct timeval timeout; { register struct ct_data *ct = (struct ct_data *) h->cl_private; register XDR *xdrs = &(ct->ct_xdrs); struct rpc_msg reply_msg; u_long x_id; u_long *msg_x_id = (u_long *)(ct->ct_mcall); /* yuk */ register bool_t shipnow; ct->ct_wait = timeout; shipnow = (xdr_results == (xdrproc_t)0 && timeout.tv_sec == 0 && timeout.tv_usec == 0) ? FALSE : TRUE; call_again: xdrs->x_op = XDR_ENCODE; ct->ct_error.re_status = RPC_SUCCESS; x_id = ntohl(--(*msg_x_id)); if ((! XDR_PUTBYTES(xdrs, ct->ct_mcall, ct->ct_mpos)) || (! XDR_PUTLONG(xdrs, (long *)&proc)) || (! AUTH_MARSHALL(h->cl_auth, xdrs)) || (! (*xdr_args)(xdrs, args_ptr))) { if (ct->ct_error.re_status == RPC_SUCCESS) ct->ct_error.re_status = RPC_CANTENCODEARGS; (void)xdrrec_endofrecord(xdrs, TRUE); return (ct->ct_error.re_status); } if (! xdrrec_endofrecord(xdrs, shipnow)) return (ct->ct_error.re_status = RPC_CANTSEND); if (! shipnow) return (RPC_SUCCESS); xdrs->x_op = XDR_DECODE; /* * Keep receiving until we get a valid transaction id */ while (TRUE) { reply_msg.acpted_rply.ar_verf = _null_auth; reply_msg.acpted_rply.ar_results.where = NULL; reply_msg.acpted_rply.ar_results.proc = xdr_void; if (! xdrrec_skiprecord(xdrs)) return (ct->ct_error.re_status); /* now decode and validate the response header */ if (! xdr_replymsg(xdrs, &reply_msg)) { if (ct->ct_error.re_status == RPC_SUCCESS) continue; return (ct->ct_error.re_status); } if (reply_msg.rm_xid == x_id) break; } /* * process header */ _seterr_reply(&reply_msg, &(ct->ct_error)); if (ct->ct_error.re_status == RPC_SUCCESS) { if (! AUTH_VALIDATE(h->cl_auth, &reply_msg.acpted_rply.ar_verf)) { ct->ct_error.re_status = RPC_AUTHERROR; ct->ct_error.re_why = AUTH_INVALIDRESP; } else if (! (*xdr_results)(xdrs, results_ptr)) { if (ct->ct_error.re_status == RPC_SUCCESS) ct->ct_error.re_status = RPC_CANTDECODERES; } /* free verifier ... */ if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) { xdrs->x_op = XDR_FREE; (void)xdr_opaque_auth(xdrs, &(reply_msg.acpted_rply.ar_verf)); } } /* end successful completion */ else { /* maybe our credentials need to be refreshed ... */ if (AUTH_REFRESH(h->cl_auth)) goto call_again; } /* end of unsuccessful completion */ return (ct->ct_error.re_status); } static void clnttcp_geterr(h, errp) CLIENT *h; struct rpc_err *errp; { register struct ct_data *ct = (struct ct_data *) h->cl_private; *errp = ct->ct_error; } static bool_t clnttcp_freeres(cl, xdr_res, res_ptr) CLIENT *cl; xdrproc_t xdr_res; caddr_t res_ptr; { register struct ct_data *ct = (struct ct_data *)cl->cl_private; register XDR *xdrs = &(ct->ct_xdrs); xdrs->x_op = XDR_FREE; return ((*xdr_res)(xdrs, res_ptr)); } static void clnttcp_abort() { } static void clnttcp_destroy(h) CLIENT *h; { register struct ct_data *ct = (struct ct_data *) h->cl_private; XDR_DESTROY(&(ct->ct_xdrs)); mem_free((caddr_t)ct, sizeof(struct ct_data)); mem_free((caddr_t)h, sizeof(CLIENT)); } /* * Interface between xdr serializer and tcp connection. * Behaves like the system calls, read & write, but keeps some error state * around for the rpc level. */ static int readtcp(ct, buf, len) register struct ct_data *ct; caddr_t buf; register int len; { register int mask = 1 << (ct->ct_sock); int readfds; while (TRUE) { readfds = mask; switch (select(32, &readfds, (int*)NULL, (int*)NULL, &(ct->ct_wait))) { case 0: ct->ct_error.re_status = RPC_TIMEDOUT; return (-1); case -1: if (errno == EINTR) continue; ct->ct_error.re_status = RPC_CANTRECV; ct->ct_error.re_errno = errno; return (-1); } if (readfds == mask) break; } if ((len = read(ct->ct_sock, buf, len)) == -1) { ct->ct_error.re_errno = errno; ct->ct_error.re_status = RPC_CANTRECV; } return (len); } static int writetcp(ct, buf, len) struct ct_data *ct; caddr_t buf; int len; { register int i, cnt; for (cnt = len; cnt > 0; cnt -= i, buf += i) { if ((i = write(ct->ct_sock, buf, cnt)) == -1) { ct->ct_error.re_errno = errno; ct->ct_error.re_status = RPC_CANTSEND; return (-1); } } return (len); } !Funky!Stuff! echo x - clnt_udp.c sed 's/^X//' >clnt_udp.c <<'!Funky!Stuff!' /* * 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 */ #ifndef lint static char sccsid[] = "@(#)clnt_udp.c 1.5 85/03/17 Copyr 1984 Sun Micro"; #endif /* * clnt_udp.c, Implements a UPD/IP based, client side RPC. * * Copyright (C) 1984, Sun Microsystems, Inc. */ #include <stdio.h> #include "types.h" #include <sys/socket.h> #include <sys/time.h> #include <netinet/in.h> #include <netdb.h> #include <errno.h> #include "xdr.h" #include "auth.h" #include "clnt.h" #include "rpc_msg.h" #include "pmap_clnt.h" char *malloc(); extern int errno; long random(); /* * UDP bases client side rpc operations */ static enum clnt_stat clntudp_call(); static void clntudp_abort(); static void clntudp_geterr(); static bool_t clntudp_freeres(); static void clntudp_destroy(); static struct clnt_ops udp_ops = { clntudp_call, clntudp_abort, clntudp_geterr, clntudp_freeres, clntudp_destroy }; /* * Private data kept per client handle */ struct cu_data { int cu_sock; struct sockaddr_in cu_raddr; int cu_rlen; struct timeval cu_wait; struct rpc_err cu_error; XDR cu_outxdrs; u_int cu_xdrpos; char cu_outbuf[UDPMSGSIZE]; char cu_inbuf[UDPMSGSIZE]; }; /* * Create a UDP based client handle. * If *sockp<0, *sockp is set to a newly created UPD socket. * If raddr->sin_port is 0 a binder on the remote machine * is consulted for the correct port number. * NB: It is the clients responsibility to close *sockp. * NB: The rpch->cl_auth is initialized to null authentication. * Caller may wish to set this something more useful. * * wait is the amount of time used between retransmitting a call if * no response has been heard; retransmition occurs until the actual * rpc call times out. */ CLIENT * clntudp_create(raddr, program, version, wait, sockp) struct sockaddr_in *raddr; u_long program; u_long version; struct timeval wait; register int *sockp; { CLIENT *cl; register struct cu_data *cu; struct timeval now; struct rpc_msg call_msg; cl = (CLIENT *)mem_alloc(sizeof(CLIENT)); if (cl == NULL) { fprintf(stderr, "clntudp_create: out of memory\n"); rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; goto fooy; } cu = (struct cu_data *)mem_alloc(sizeof(*cu)); if (cu == NULL) { fprintf(stderr, "clntudp_create: out of memory\n"); rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; goto fooy; } (void)gettimeofday(&now, (struct timezone *)0); if (raddr->sin_port == 0) { u_short port; if ((port = pmap_getport(raddr, program, version, IPPROTO_UDP)) == 0) { goto fooy; } raddr->sin_port = htons(port); } cl->cl_ops = &udp_ops; cl->cl_private = (caddr_t)cu; cu->cu_raddr = *raddr; cu->cu_rlen = sizeof (cu->cu_raddr); cu->cu_wait = wait; call_msg.rm_xid = getpid() ^ (int)random() ^ now.tv_sec ^ now.tv_usec; call_msg.rm_direction = CALL; call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; call_msg.rm_call.cb_prog = program; call_msg.rm_call.cb_vers = version; xdrmem_create(&(cu->cu_outxdrs), cu->cu_outbuf, UDPMSGSIZE, XDR_ENCODE); if (! xdr_callhdr(&(cu->cu_outxdrs), &call_msg)) { goto fooy; } cu->cu_xdrpos = XDR_GETPOS(&(cu->cu_outxdrs)); cu->cu_sock = (*sockp < 0) ? (*sockp = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) : *sockp; if (cu->cu_sock < 0) { rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; goto fooy; } cl->cl_auth = authnone_create(); return (cl); fooy: mem_free((caddr_t)cu, sizeof(*cu)); mem_free((caddr_t)cl, sizeof(CLIENT)); return ((CLIENT *)NULL); } static enum clnt_stat clntudp_call(cl, proc, xargs, argsp, xresults, resultsp, timeout) register CLIENT *cl; /* client handle */ u_long proc; /* procedure number */ xdrproc_t xargs; /* xdr routine for args */ caddr_t argsp; /* pointer to args */ xdrproc_t xresults; /* xdr routine for results */ caddr_t resultsp; /* pointer to results */ struct timeval timeout; /* seconds to wait before giving up */ { register struct cu_data *cu = (struct cu_data *)cl->cl_private; register XDR *xdrs; register int outlen; register int inlen; int readfds, fromlen; register int mask; struct sockaddr_in from; struct rpc_msg reply_msg; XDR reply_xdrs; struct timeval time_waited; bool_t ok; call_again: time_waited.tv_sec = 0; time_waited.tv_usec = 0; xdrs = &(cu->cu_outxdrs); xdrs->x_op = XDR_ENCODE; XDR_SETPOS(xdrs, cu->cu_xdrpos); /* * the transaction is the first thing in the out buffer */ (*(u_short *)(cu->cu_outbuf))++; if ((! XDR_PUTLONG(xdrs, (long *)&proc)) || (! AUTH_MARSHALL(cl->cl_auth, xdrs)) || (! (*xargs)(xdrs, argsp))) return (cu->cu_error.re_status = RPC_CANTENCODEARGS); outlen = (int)XDR_GETPOS(xdrs); while (TRUE) { if (sendto(cu->cu_sock, cu->cu_outbuf, outlen, 0, (struct sockaddr *)&(cu->cu_raddr), cu->cu_rlen) != outlen) { cu->cu_error.re_errno = errno; return (cu->cu_error.re_status = RPC_CANTSEND); } /* * sub-optimal code appears inside the loop because we have * some clock time to spare while the packets are in flight. * (We assume that this is actually only executed once.) */ reply_msg.acpted_rply.ar_verf = _null_auth; reply_msg.acpted_rply.ar_results.where = resultsp; reply_msg.acpted_rply.ar_results.proc = xresults; mask = 1 << cu->cu_sock; rcv_again: readfds = mask; switch (select(32, &readfds, (int *)NULL, (int *)NULL, &(cu->cu_wait))) { case 0: time_waited.tv_sec += cu->cu_wait.tv_sec; time_waited.tv_usec += cu->cu_wait.tv_usec; while (time_waited.tv_usec >= 1000000) { time_waited.tv_sec++; time_waited.tv_usec -= 1000000; } if ((time_waited.tv_sec < timeout.tv_sec) || ((time_waited.tv_sec == timeout.tv_sec) && (time_waited.tv_usec < timeout.tv_usec))) continue; return (cu->cu_error.re_status = RPC_TIMEDOUT); case -1: if (errno == EINTR) goto rcv_again; cu->cu_error.re_errno = errno; return (cu->cu_error.re_status = RPC_CANTRECV); } if ((readfds & mask) == 0) goto rcv_again; tryagain: fromlen = sizeof(struct sockaddr); inlen = recvfrom(cu->cu_sock, cu->cu_inbuf, UDPMSGSIZE, 0, (struct sockaddr *)&from, &fromlen); if (inlen < 0) { if (errno == EINTR) goto tryagain; cu->cu_error.re_errno = errno; return (cu->cu_error.re_status = RPC_CANTRECV); } if (inlen < sizeof(u_long)) goto rcv_again; /* see if reply transaction id matches sent id */ if (*((u_long *)(cu->cu_inbuf)) != *((u_long *)(cu->cu_outbuf))) goto rcv_again; /* we now assume we have the proper reply */ break; } /* * now decode and validate the response */ xdrmem_create(&reply_xdrs, cu->cu_inbuf, (u_int)inlen, XDR_DECODE); ok = xdr_replymsg(&reply_xdrs, &reply_msg); /* XDR_DESTROY(&reply_xdrs); save a few cycles on noop destroy */ if (ok) { _seterr_reply(&reply_msg, &(cu->cu_error)); if (cu->cu_error.re_status == RPC_SUCCESS) { if (! AUTH_VALIDATE(cl->cl_auth, &reply_msg.acpted_rply.ar_verf)) { cu->cu_error.re_status = RPC_AUTHERROR; cu->cu_error.re_why = AUTH_INVALIDRESP; } if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) { xdrs->x_op = XDR_FREE; (void)xdr_opaque_auth(xdrs, &(reply_msg.acpted_rply.ar_verf)); } } /* end successful completion */ else { /* maybe our credentials need to be refreshed ... */ if (AUTH_REFRESH(cl->cl_auth)) goto call_again; } /* end of unsuccessful completion */ } /* end of valid reply message */ else { cu->cu_error.re_status = RPC_CANTDECODERES; } return (cu->cu_error.re_status); } static void clntudp_geterr(cl, errp) CLIENT *cl; struct rpc_err *errp; { register struct cu_data *cu = (struct cu_data *)cl->cl_private; *errp = cu->cu_error; } static bool_t clntudp_freeres(cl, xdr_res, res_ptr) CLIENT *cl; xdrproc_t xdr_res; caddr_t res_ptr; { register struct cu_data *cu = (struct cu_data *)cl->cl_private; register XDR *xdrs = &(cu->cu_outxdrs); xdrs->x_op = XDR_FREE; return ((*xdr_res)(xdrs, res_ptr)); } static void clntudp_abort(/*h*/) /*CLIENT *h;*/ { } static void clntudp_destroy(cl) CLIENT *cl; { register struct cu_data *cu = (struct cu_data *)cl->cl_private; XDR_DESTROY(&(cu->cu_outxdrs)); mem_free((caddr_t)cu, sizeof(*cu)); mem_free((caddr_t)cl, sizeof(CLIENT)); } !Funky!Stuff! exit