18360efbdSAlfred Perlstein /* $NetBSD: rpc_prot.c,v 1.16 2000/06/02 23:11:13 fvdl Exp $ */ 28360efbdSAlfred Perlstein 3*2e322d37SHiroki Sato /*- 4*2e322d37SHiroki Sato * Copyright (c) 2009, Sun Microsystems, Inc. 5*2e322d37SHiroki Sato * All rights reserved. 699064799SGarrett Wollman * 7*2e322d37SHiroki Sato * Redistribution and use in source and binary forms, with or without 8*2e322d37SHiroki Sato * modification, are permitted provided that the following conditions are met: 9*2e322d37SHiroki Sato * - Redistributions of source code must retain the above copyright notice, 10*2e322d37SHiroki Sato * this list of conditions and the following disclaimer. 11*2e322d37SHiroki Sato * - Redistributions in binary form must reproduce the above copyright notice, 12*2e322d37SHiroki Sato * this list of conditions and the following disclaimer in the documentation 13*2e322d37SHiroki Sato * and/or other materials provided with the distribution. 14*2e322d37SHiroki Sato * - Neither the name of Sun Microsystems, Inc. nor the names of its 15*2e322d37SHiroki Sato * contributors may be used to endorse or promote products derived 16*2e322d37SHiroki Sato * from this software without specific prior written permission. 1799064799SGarrett Wollman * 18*2e322d37SHiroki Sato * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19*2e322d37SHiroki Sato * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20*2e322d37SHiroki Sato * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21*2e322d37SHiroki Sato * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22*2e322d37SHiroki Sato * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23*2e322d37SHiroki Sato * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24*2e322d37SHiroki Sato * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25*2e322d37SHiroki Sato * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26*2e322d37SHiroki Sato * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27*2e322d37SHiroki Sato * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28*2e322d37SHiroki Sato * POSSIBILITY OF SUCH DAMAGE. 2999064799SGarrett Wollman */ 3099064799SGarrett Wollman 3199064799SGarrett Wollman #if defined(LIBC_SCCS) && !defined(lint) 32a986ef57SDavid E. O'Brien static char *sccsid2 = "@(#)rpc_prot.c 1.36 87/08/11 Copyr 1984 Sun Micro"; 338360efbdSAlfred Perlstein static char *sccsid = "@(#)rpc_prot.c 2.3 88/08/07 4.0 RPCSRC"; 3499064799SGarrett Wollman #endif 35d3d20c82SDavid E. O'Brien #include <sys/cdefs.h> 36d3d20c82SDavid E. O'Brien __FBSDID("$FreeBSD$"); 3799064799SGarrett Wollman 3899064799SGarrett Wollman /* 3999064799SGarrett Wollman * rpc_prot.c 4099064799SGarrett Wollman * 4199064799SGarrett Wollman * Copyright (C) 1984, Sun Microsystems, Inc. 4299064799SGarrett Wollman * 4399064799SGarrett Wollman * This set of routines implements the rpc message definition, 4499064799SGarrett Wollman * its serializer and some common rpc utility routines. 4599064799SGarrett Wollman * The routines are meant for various implementations of rpc - 4699064799SGarrett Wollman * they are NOT for the rpc client or rpc service implementations! 4799064799SGarrett Wollman * Because authentication stuff is easy and is part of rpc, the opaque 4899064799SGarrett Wollman * routines are also in this program. 4999064799SGarrett Wollman */ 5099064799SGarrett Wollman 518360efbdSAlfred Perlstein #include "namespace.h" 5299064799SGarrett Wollman #include <sys/param.h> 5399064799SGarrett Wollman 548360efbdSAlfred Perlstein #include <assert.h> 558360efbdSAlfred Perlstein 5699064799SGarrett Wollman #include <rpc/rpc.h> 578360efbdSAlfred Perlstein #include "un-namespace.h" 588360efbdSAlfred Perlstein 59c05ac53bSDavid E. O'Brien static void accepted(enum accept_stat, struct rpc_err *); 60c05ac53bSDavid E. O'Brien static void rejected(enum reject_stat, struct rpc_err *); 6199064799SGarrett Wollman 6299064799SGarrett Wollman /* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */ 6399064799SGarrett Wollman 648360efbdSAlfred Perlstein extern struct opaque_auth _null_auth; 6599064799SGarrett Wollman 6699064799SGarrett Wollman /* 6799064799SGarrett Wollman * XDR an opaque authentication struct 6899064799SGarrett Wollman * (see auth.h) 6999064799SGarrett Wollman */ 7099064799SGarrett Wollman bool_t 7199064799SGarrett Wollman xdr_opaque_auth(xdrs, ap) 728360efbdSAlfred Perlstein XDR *xdrs; 738360efbdSAlfred Perlstein struct opaque_auth *ap; 7499064799SGarrett Wollman { 7599064799SGarrett Wollman 768360efbdSAlfred Perlstein assert(xdrs != NULL); 778360efbdSAlfred Perlstein assert(ap != NULL); 788360efbdSAlfred Perlstein 7999064799SGarrett Wollman if (xdr_enum(xdrs, &(ap->oa_flavor))) 8099064799SGarrett Wollman return (xdr_bytes(xdrs, &ap->oa_base, 8199064799SGarrett Wollman &ap->oa_length, MAX_AUTH_BYTES)); 8299064799SGarrett Wollman return (FALSE); 8399064799SGarrett Wollman } 8499064799SGarrett Wollman 8599064799SGarrett Wollman /* 8699064799SGarrett Wollman * XDR a DES block 8799064799SGarrett Wollman */ 8899064799SGarrett Wollman bool_t 8999064799SGarrett Wollman xdr_des_block(xdrs, blkp) 908360efbdSAlfred Perlstein XDR *xdrs; 918360efbdSAlfred Perlstein des_block *blkp; 9299064799SGarrett Wollman { 938360efbdSAlfred Perlstein 948360efbdSAlfred Perlstein assert(xdrs != NULL); 958360efbdSAlfred Perlstein assert(blkp != NULL); 968360efbdSAlfred Perlstein 978360efbdSAlfred Perlstein return (xdr_opaque(xdrs, (caddr_t)(void *)blkp, sizeof(des_block))); 9899064799SGarrett Wollman } 9999064799SGarrett Wollman 10099064799SGarrett Wollman /* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */ 10199064799SGarrett Wollman 10299064799SGarrett Wollman /* 10399064799SGarrett Wollman * XDR the MSG_ACCEPTED part of a reply message union 10499064799SGarrett Wollman */ 10599064799SGarrett Wollman bool_t 10699064799SGarrett Wollman xdr_accepted_reply(xdrs, ar) 1078360efbdSAlfred Perlstein XDR *xdrs; 1088360efbdSAlfred Perlstein struct accepted_reply *ar; 10999064799SGarrett Wollman { 110102c7c92SJohn Birrell enum accept_stat *par_stat; 11199064799SGarrett Wollman 1128360efbdSAlfred Perlstein assert(xdrs != NULL); 1138360efbdSAlfred Perlstein assert(ar != NULL); 1148360efbdSAlfred Perlstein 115102c7c92SJohn Birrell par_stat = &ar->ar_stat; 116102c7c92SJohn Birrell 11799064799SGarrett Wollman /* personalized union, rather than calling xdr_union */ 11899064799SGarrett Wollman if (! xdr_opaque_auth(xdrs, &(ar->ar_verf))) 11999064799SGarrett Wollman return (FALSE); 120102c7c92SJohn Birrell if (! xdr_enum(xdrs, (enum_t *) par_stat)) 12199064799SGarrett Wollman return (FALSE); 12299064799SGarrett Wollman switch (ar->ar_stat) { 12399064799SGarrett Wollman 12499064799SGarrett Wollman case SUCCESS: 12599064799SGarrett Wollman return ((*(ar->ar_results.proc))(xdrs, ar->ar_results.where)); 12699064799SGarrett Wollman 12799064799SGarrett Wollman case PROG_MISMATCH: 12839f37784SPeter Wemm if (! xdr_u_int32_t(xdrs, &(ar->ar_vers.low))) 12999064799SGarrett Wollman return (FALSE); 13039f37784SPeter Wemm return (xdr_u_int32_t(xdrs, &(ar->ar_vers.high))); 1318360efbdSAlfred Perlstein 1328360efbdSAlfred Perlstein case GARBAGE_ARGS: 1338360efbdSAlfred Perlstein case SYSTEM_ERR: 1348360efbdSAlfred Perlstein case PROC_UNAVAIL: 1358360efbdSAlfred Perlstein case PROG_UNAVAIL: 136f12d1a5dSJames Raynard break; 13799064799SGarrett Wollman } 13899064799SGarrett Wollman return (TRUE); /* TRUE => open ended set of problems */ 13999064799SGarrett Wollman } 14099064799SGarrett Wollman 14199064799SGarrett Wollman /* 14299064799SGarrett Wollman * XDR the MSG_DENIED part of a reply message union 14399064799SGarrett Wollman */ 14499064799SGarrett Wollman bool_t 14599064799SGarrett Wollman xdr_rejected_reply(xdrs, rr) 1468360efbdSAlfred Perlstein XDR *xdrs; 1478360efbdSAlfred Perlstein struct rejected_reply *rr; 14899064799SGarrett Wollman { 149102c7c92SJohn Birrell enum reject_stat *prj_stat; 150102c7c92SJohn Birrell enum auth_stat *prj_why; 15199064799SGarrett Wollman 1528360efbdSAlfred Perlstein assert(xdrs != NULL); 1538360efbdSAlfred Perlstein assert(rr != NULL); 1548360efbdSAlfred Perlstein 155102c7c92SJohn Birrell prj_stat = &rr->rj_stat; 156102c7c92SJohn Birrell 15799064799SGarrett Wollman /* personalized union, rather than calling xdr_union */ 158102c7c92SJohn Birrell if (! xdr_enum(xdrs, (enum_t *) prj_stat)) 15999064799SGarrett Wollman return (FALSE); 16099064799SGarrett Wollman switch (rr->rj_stat) { 16199064799SGarrett Wollman 16299064799SGarrett Wollman case RPC_MISMATCH: 16339f37784SPeter Wemm if (! xdr_u_int32_t(xdrs, &(rr->rj_vers.low))) 16499064799SGarrett Wollman return (FALSE); 16539f37784SPeter Wemm return (xdr_u_int32_t(xdrs, &(rr->rj_vers.high))); 16699064799SGarrett Wollman 16799064799SGarrett Wollman case AUTH_ERROR: 168102c7c92SJohn Birrell prj_why = &rr->rj_why; 169102c7c92SJohn Birrell return (xdr_enum(xdrs, (enum_t *) prj_why)); 17099064799SGarrett Wollman } 1718360efbdSAlfred Perlstein /* NOTREACHED */ 1728360efbdSAlfred Perlstein assert(0); 17399064799SGarrett Wollman return (FALSE); 17499064799SGarrett Wollman } 17599064799SGarrett Wollman 1768360efbdSAlfred Perlstein static const struct xdr_discrim reply_dscrm[3] = { 1778360efbdSAlfred Perlstein { (int)MSG_ACCEPTED, (xdrproc_t)xdr_accepted_reply }, 1788360efbdSAlfred Perlstein { (int)MSG_DENIED, (xdrproc_t)xdr_rejected_reply }, 17999064799SGarrett Wollman { __dontcare__, NULL_xdrproc_t } }; 18099064799SGarrett Wollman 18199064799SGarrett Wollman /* 18299064799SGarrett Wollman * XDR a reply message 18399064799SGarrett Wollman */ 18499064799SGarrett Wollman bool_t 18599064799SGarrett Wollman xdr_replymsg(xdrs, rmsg) 1868360efbdSAlfred Perlstein XDR *xdrs; 1878360efbdSAlfred Perlstein struct rpc_msg *rmsg; 18899064799SGarrett Wollman { 189102c7c92SJohn Birrell enum msg_type *prm_direction; 190102c7c92SJohn Birrell enum reply_stat *prp_stat; 191102c7c92SJohn Birrell 1928360efbdSAlfred Perlstein assert(xdrs != NULL); 1938360efbdSAlfred Perlstein assert(rmsg != NULL); 1948360efbdSAlfred Perlstein 195102c7c92SJohn Birrell prm_direction = &rmsg->rm_direction; 196102c7c92SJohn Birrell prp_stat = &rmsg->rm_reply.rp_stat; 197102c7c92SJohn Birrell 19899064799SGarrett Wollman if ( 19939f37784SPeter Wemm xdr_u_int32_t(xdrs, &(rmsg->rm_xid)) && 200102c7c92SJohn Birrell xdr_enum(xdrs, (enum_t *) prm_direction) && 20199064799SGarrett Wollman (rmsg->rm_direction == REPLY) ) 202102c7c92SJohn Birrell return (xdr_union(xdrs, (enum_t *) prp_stat, 2038360efbdSAlfred Perlstein (caddr_t)(void *)&(rmsg->rm_reply.ru), reply_dscrm, 2048360efbdSAlfred Perlstein NULL_xdrproc_t)); 20599064799SGarrett Wollman return (FALSE); 20699064799SGarrett Wollman } 20799064799SGarrett Wollman 20899064799SGarrett Wollman 20999064799SGarrett Wollman /* 21099064799SGarrett Wollman * Serializes the "static part" of a call message header. 21199064799SGarrett Wollman * The fields include: rm_xid, rm_direction, rpcvers, prog, and vers. 21299064799SGarrett Wollman * The rm_xid is not really static, but the user can easily munge on the fly. 21399064799SGarrett Wollman */ 21499064799SGarrett Wollman bool_t 21599064799SGarrett Wollman xdr_callhdr(xdrs, cmsg) 2168360efbdSAlfred Perlstein XDR *xdrs; 2178360efbdSAlfred Perlstein struct rpc_msg *cmsg; 21899064799SGarrett Wollman { 219102c7c92SJohn Birrell enum msg_type *prm_direction; 22099064799SGarrett Wollman 2218360efbdSAlfred Perlstein assert(xdrs != NULL); 2228360efbdSAlfred Perlstein assert(cmsg != NULL); 2238360efbdSAlfred Perlstein 224102c7c92SJohn Birrell prm_direction = &cmsg->rm_direction; 225102c7c92SJohn Birrell 22699064799SGarrett Wollman cmsg->rm_direction = CALL; 22799064799SGarrett Wollman cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION; 22899064799SGarrett Wollman if ( 22999064799SGarrett Wollman (xdrs->x_op == XDR_ENCODE) && 23039f37784SPeter Wemm xdr_u_int32_t(xdrs, &(cmsg->rm_xid)) && 231102c7c92SJohn Birrell xdr_enum(xdrs, (enum_t *) prm_direction) && 23239f37784SPeter Wemm xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_rpcvers)) && 23339f37784SPeter Wemm xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_prog)) ) 23439f37784SPeter Wemm return (xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_vers))); 23599064799SGarrett Wollman return (FALSE); 23699064799SGarrett Wollman } 23799064799SGarrett Wollman 23899064799SGarrett Wollman /* ************************** Client utility routine ************* */ 23999064799SGarrett Wollman 24099064799SGarrett Wollman static void 24199064799SGarrett Wollman accepted(acpt_stat, error) 2428360efbdSAlfred Perlstein enum accept_stat acpt_stat; 2438360efbdSAlfred Perlstein struct rpc_err *error; 24499064799SGarrett Wollman { 24599064799SGarrett Wollman 2468360efbdSAlfred Perlstein assert(error != NULL); 2478360efbdSAlfred Perlstein 24899064799SGarrett Wollman switch (acpt_stat) { 24999064799SGarrett Wollman 25099064799SGarrett Wollman case PROG_UNAVAIL: 25199064799SGarrett Wollman error->re_status = RPC_PROGUNAVAIL; 25299064799SGarrett Wollman return; 25399064799SGarrett Wollman 25499064799SGarrett Wollman case PROG_MISMATCH: 25599064799SGarrett Wollman error->re_status = RPC_PROGVERSMISMATCH; 25699064799SGarrett Wollman return; 25799064799SGarrett Wollman 25899064799SGarrett Wollman case PROC_UNAVAIL: 25999064799SGarrett Wollman error->re_status = RPC_PROCUNAVAIL; 26099064799SGarrett Wollman return; 26199064799SGarrett Wollman 26299064799SGarrett Wollman case GARBAGE_ARGS: 26399064799SGarrett Wollman error->re_status = RPC_CANTDECODEARGS; 26499064799SGarrett Wollman return; 26599064799SGarrett Wollman 26699064799SGarrett Wollman case SYSTEM_ERR: 26799064799SGarrett Wollman error->re_status = RPC_SYSTEMERROR; 26899064799SGarrett Wollman return; 26999064799SGarrett Wollman 27099064799SGarrett Wollman case SUCCESS: 27199064799SGarrett Wollman error->re_status = RPC_SUCCESS; 27299064799SGarrett Wollman return; 27399064799SGarrett Wollman } 2748360efbdSAlfred Perlstein /* NOTREACHED */ 27599064799SGarrett Wollman /* something's wrong, but we don't know what ... */ 27699064799SGarrett Wollman error->re_status = RPC_FAILED; 2778360efbdSAlfred Perlstein error->re_lb.s1 = (int32_t)MSG_ACCEPTED; 2788360efbdSAlfred Perlstein error->re_lb.s2 = (int32_t)acpt_stat; 27999064799SGarrett Wollman } 28099064799SGarrett Wollman 28199064799SGarrett Wollman static void 28299064799SGarrett Wollman rejected(rjct_stat, error) 2838360efbdSAlfred Perlstein enum reject_stat rjct_stat; 2848360efbdSAlfred Perlstein struct rpc_err *error; 28599064799SGarrett Wollman { 28699064799SGarrett Wollman 2878360efbdSAlfred Perlstein assert(error != NULL); 28899064799SGarrett Wollman 2898360efbdSAlfred Perlstein switch (rjct_stat) { 2908360efbdSAlfred Perlstein case RPC_MISMATCH: 29199064799SGarrett Wollman error->re_status = RPC_VERSMISMATCH; 29299064799SGarrett Wollman return; 29399064799SGarrett Wollman 29499064799SGarrett Wollman case AUTH_ERROR: 29599064799SGarrett Wollman error->re_status = RPC_AUTHERROR; 29699064799SGarrett Wollman return; 29799064799SGarrett Wollman } 29899064799SGarrett Wollman /* something's wrong, but we don't know what ... */ 2998360efbdSAlfred Perlstein /* NOTREACHED */ 30099064799SGarrett Wollman error->re_status = RPC_FAILED; 3018360efbdSAlfred Perlstein error->re_lb.s1 = (int32_t)MSG_DENIED; 3028360efbdSAlfred Perlstein error->re_lb.s2 = (int32_t)rjct_stat; 30399064799SGarrett Wollman } 30499064799SGarrett Wollman 30599064799SGarrett Wollman /* 30699064799SGarrett Wollman * given a reply message, fills in the error 30799064799SGarrett Wollman */ 30899064799SGarrett Wollman void 30999064799SGarrett Wollman _seterr_reply(msg, error) 3108360efbdSAlfred Perlstein struct rpc_msg *msg; 3118360efbdSAlfred Perlstein struct rpc_err *error; 31299064799SGarrett Wollman { 31399064799SGarrett Wollman 3148360efbdSAlfred Perlstein assert(msg != NULL); 3158360efbdSAlfred Perlstein assert(error != NULL); 3168360efbdSAlfred Perlstein 31799064799SGarrett Wollman /* optimized for normal, SUCCESSful case */ 31899064799SGarrett Wollman switch (msg->rm_reply.rp_stat) { 31999064799SGarrett Wollman 32099064799SGarrett Wollman case MSG_ACCEPTED: 32199064799SGarrett Wollman if (msg->acpted_rply.ar_stat == SUCCESS) { 32299064799SGarrett Wollman error->re_status = RPC_SUCCESS; 32399064799SGarrett Wollman return; 3248360efbdSAlfred Perlstein } 32599064799SGarrett Wollman accepted(msg->acpted_rply.ar_stat, error); 32699064799SGarrett Wollman break; 32799064799SGarrett Wollman 32899064799SGarrett Wollman case MSG_DENIED: 32999064799SGarrett Wollman rejected(msg->rjcted_rply.rj_stat, error); 33099064799SGarrett Wollman break; 33199064799SGarrett Wollman 33299064799SGarrett Wollman default: 33399064799SGarrett Wollman error->re_status = RPC_FAILED; 3348360efbdSAlfred Perlstein error->re_lb.s1 = (int32_t)(msg->rm_reply.rp_stat); 33599064799SGarrett Wollman break; 33699064799SGarrett Wollman } 33799064799SGarrett Wollman switch (error->re_status) { 33899064799SGarrett Wollman 33999064799SGarrett Wollman case RPC_VERSMISMATCH: 34099064799SGarrett Wollman error->re_vers.low = msg->rjcted_rply.rj_vers.low; 34199064799SGarrett Wollman error->re_vers.high = msg->rjcted_rply.rj_vers.high; 34299064799SGarrett Wollman break; 34399064799SGarrett Wollman 34499064799SGarrett Wollman case RPC_AUTHERROR: 34599064799SGarrett Wollman error->re_why = msg->rjcted_rply.rj_why; 34699064799SGarrett Wollman break; 34799064799SGarrett Wollman 34899064799SGarrett Wollman case RPC_PROGVERSMISMATCH: 34999064799SGarrett Wollman error->re_vers.low = msg->acpted_rply.ar_vers.low; 35099064799SGarrett Wollman error->re_vers.high = msg->acpted_rply.ar_vers.high; 35199064799SGarrett Wollman break; 3528360efbdSAlfred Perlstein 3538360efbdSAlfred Perlstein case RPC_FAILED: 3548360efbdSAlfred Perlstein case RPC_SUCCESS: 3558360efbdSAlfred Perlstein case RPC_PROGNOTREGISTERED: 3568360efbdSAlfred Perlstein case RPC_PMAPFAILURE: 3578360efbdSAlfred Perlstein case RPC_UNKNOWNPROTO: 3588360efbdSAlfred Perlstein case RPC_UNKNOWNHOST: 3598360efbdSAlfred Perlstein case RPC_SYSTEMERROR: 3608360efbdSAlfred Perlstein case RPC_CANTDECODEARGS: 3618360efbdSAlfred Perlstein case RPC_PROCUNAVAIL: 3628360efbdSAlfred Perlstein case RPC_PROGUNAVAIL: 3638360efbdSAlfred Perlstein case RPC_TIMEDOUT: 3648360efbdSAlfred Perlstein case RPC_CANTRECV: 3658360efbdSAlfred Perlstein case RPC_CANTSEND: 3668360efbdSAlfred Perlstein case RPC_CANTDECODERES: 3678360efbdSAlfred Perlstein case RPC_CANTENCODEARGS: 368f12d1a5dSJames Raynard default: 369f12d1a5dSJames Raynard break; 37099064799SGarrett Wollman } 37199064799SGarrett Wollman } 372