18360efbdSAlfred Perlstein /* $NetBSD: rpc_prot.c,v 1.16 2000/06/02 23:11:13 fvdl Exp $ */ 28360efbdSAlfred Perlstein 32e322d37SHiroki Sato /*- 42e322d37SHiroki Sato * Copyright (c) 2009, Sun Microsystems, Inc. 52e322d37SHiroki Sato * All rights reserved. 699064799SGarrett Wollman * 72e322d37SHiroki Sato * Redistribution and use in source and binary forms, with or without 82e322d37SHiroki Sato * modification, are permitted provided that the following conditions are met: 92e322d37SHiroki Sato * - Redistributions of source code must retain the above copyright notice, 102e322d37SHiroki Sato * this list of conditions and the following disclaimer. 112e322d37SHiroki Sato * - Redistributions in binary form must reproduce the above copyright notice, 122e322d37SHiroki Sato * this list of conditions and the following disclaimer in the documentation 132e322d37SHiroki Sato * and/or other materials provided with the distribution. 142e322d37SHiroki Sato * - Neither the name of Sun Microsystems, Inc. nor the names of its 152e322d37SHiroki Sato * contributors may be used to endorse or promote products derived 162e322d37SHiroki Sato * from this software without specific prior written permission. 1799064799SGarrett Wollman * 182e322d37SHiroki Sato * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 192e322d37SHiroki Sato * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 202e322d37SHiroki Sato * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 212e322d37SHiroki Sato * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 222e322d37SHiroki Sato * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 232e322d37SHiroki Sato * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 242e322d37SHiroki Sato * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 252e322d37SHiroki Sato * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 262e322d37SHiroki Sato * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 272e322d37SHiroki Sato * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 282e322d37SHiroki 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 71*a7c2cd38SCraig Rodrigues xdr_opaque_auth(XDR *xdrs, struct opaque_auth *ap) 7299064799SGarrett Wollman { 7399064799SGarrett Wollman 748360efbdSAlfred Perlstein assert(xdrs != NULL); 758360efbdSAlfred Perlstein assert(ap != NULL); 768360efbdSAlfred Perlstein 7799064799SGarrett Wollman if (xdr_enum(xdrs, &(ap->oa_flavor))) 7899064799SGarrett Wollman return (xdr_bytes(xdrs, &ap->oa_base, 7999064799SGarrett Wollman &ap->oa_length, MAX_AUTH_BYTES)); 8099064799SGarrett Wollman return (FALSE); 8199064799SGarrett Wollman } 8299064799SGarrett Wollman 8399064799SGarrett Wollman /* 8499064799SGarrett Wollman * XDR a DES block 8599064799SGarrett Wollman */ 8699064799SGarrett Wollman bool_t 87*a7c2cd38SCraig Rodrigues xdr_des_block(XDR *xdrs, des_block *blkp) 8899064799SGarrett Wollman { 898360efbdSAlfred Perlstein 908360efbdSAlfred Perlstein assert(xdrs != NULL); 918360efbdSAlfred Perlstein assert(blkp != NULL); 928360efbdSAlfred Perlstein 938360efbdSAlfred Perlstein return (xdr_opaque(xdrs, (caddr_t)(void *)blkp, sizeof(des_block))); 9499064799SGarrett Wollman } 9599064799SGarrett Wollman 9699064799SGarrett Wollman /* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */ 9799064799SGarrett Wollman 9899064799SGarrett Wollman /* 9999064799SGarrett Wollman * XDR the MSG_ACCEPTED part of a reply message union 10099064799SGarrett Wollman */ 10199064799SGarrett Wollman bool_t 102*a7c2cd38SCraig Rodrigues xdr_accepted_reply(XDR *xdrs, struct accepted_reply *ar) 10399064799SGarrett Wollman { 104102c7c92SJohn Birrell enum accept_stat *par_stat; 10599064799SGarrett Wollman 1068360efbdSAlfred Perlstein assert(xdrs != NULL); 1078360efbdSAlfred Perlstein assert(ar != NULL); 1088360efbdSAlfred Perlstein 109102c7c92SJohn Birrell par_stat = &ar->ar_stat; 110102c7c92SJohn Birrell 11199064799SGarrett Wollman /* personalized union, rather than calling xdr_union */ 11299064799SGarrett Wollman if (! xdr_opaque_auth(xdrs, &(ar->ar_verf))) 11399064799SGarrett Wollman return (FALSE); 114102c7c92SJohn Birrell if (! xdr_enum(xdrs, (enum_t *) par_stat)) 11599064799SGarrett Wollman return (FALSE); 11699064799SGarrett Wollman switch (ar->ar_stat) { 11799064799SGarrett Wollman 11899064799SGarrett Wollman case SUCCESS: 11999064799SGarrett Wollman return ((*(ar->ar_results.proc))(xdrs, ar->ar_results.where)); 12099064799SGarrett Wollman 12199064799SGarrett Wollman case PROG_MISMATCH: 12239f37784SPeter Wemm if (! xdr_u_int32_t(xdrs, &(ar->ar_vers.low))) 12399064799SGarrett Wollman return (FALSE); 12439f37784SPeter Wemm return (xdr_u_int32_t(xdrs, &(ar->ar_vers.high))); 1258360efbdSAlfred Perlstein 1268360efbdSAlfred Perlstein case GARBAGE_ARGS: 1278360efbdSAlfred Perlstein case SYSTEM_ERR: 1288360efbdSAlfred Perlstein case PROC_UNAVAIL: 1298360efbdSAlfred Perlstein case PROG_UNAVAIL: 130f12d1a5dSJames Raynard break; 13199064799SGarrett Wollman } 13299064799SGarrett Wollman return (TRUE); /* TRUE => open ended set of problems */ 13399064799SGarrett Wollman } 13499064799SGarrett Wollman 13599064799SGarrett Wollman /* 13699064799SGarrett Wollman * XDR the MSG_DENIED part of a reply message union 13799064799SGarrett Wollman */ 13899064799SGarrett Wollman bool_t 139*a7c2cd38SCraig Rodrigues xdr_rejected_reply(XDR *xdrs, struct rejected_reply *rr) 14099064799SGarrett Wollman { 141102c7c92SJohn Birrell enum reject_stat *prj_stat; 142102c7c92SJohn Birrell enum auth_stat *prj_why; 14399064799SGarrett Wollman 1448360efbdSAlfred Perlstein assert(xdrs != NULL); 1458360efbdSAlfred Perlstein assert(rr != NULL); 1468360efbdSAlfred Perlstein 147102c7c92SJohn Birrell prj_stat = &rr->rj_stat; 148102c7c92SJohn Birrell 14999064799SGarrett Wollman /* personalized union, rather than calling xdr_union */ 150102c7c92SJohn Birrell if (! xdr_enum(xdrs, (enum_t *) prj_stat)) 15199064799SGarrett Wollman return (FALSE); 15299064799SGarrett Wollman switch (rr->rj_stat) { 15399064799SGarrett Wollman 15499064799SGarrett Wollman case RPC_MISMATCH: 15539f37784SPeter Wemm if (! xdr_u_int32_t(xdrs, &(rr->rj_vers.low))) 15699064799SGarrett Wollman return (FALSE); 15739f37784SPeter Wemm return (xdr_u_int32_t(xdrs, &(rr->rj_vers.high))); 15899064799SGarrett Wollman 15999064799SGarrett Wollman case AUTH_ERROR: 160102c7c92SJohn Birrell prj_why = &rr->rj_why; 161102c7c92SJohn Birrell return (xdr_enum(xdrs, (enum_t *) prj_why)); 16299064799SGarrett Wollman } 1638360efbdSAlfred Perlstein /* NOTREACHED */ 1648360efbdSAlfred Perlstein assert(0); 16599064799SGarrett Wollman return (FALSE); 16699064799SGarrett Wollman } 16799064799SGarrett Wollman 1688360efbdSAlfred Perlstein static const struct xdr_discrim reply_dscrm[3] = { 1698360efbdSAlfred Perlstein { (int)MSG_ACCEPTED, (xdrproc_t)xdr_accepted_reply }, 1708360efbdSAlfred Perlstein { (int)MSG_DENIED, (xdrproc_t)xdr_rejected_reply }, 17199064799SGarrett Wollman { __dontcare__, NULL_xdrproc_t } }; 17299064799SGarrett Wollman 17399064799SGarrett Wollman /* 17499064799SGarrett Wollman * XDR a reply message 17599064799SGarrett Wollman */ 17699064799SGarrett Wollman bool_t 177*a7c2cd38SCraig Rodrigues xdr_replymsg(XDR *xdrs, struct rpc_msg *rmsg) 17899064799SGarrett Wollman { 179102c7c92SJohn Birrell enum msg_type *prm_direction; 180102c7c92SJohn Birrell enum reply_stat *prp_stat; 181102c7c92SJohn Birrell 1828360efbdSAlfred Perlstein assert(xdrs != NULL); 1838360efbdSAlfred Perlstein assert(rmsg != NULL); 1848360efbdSAlfred Perlstein 185102c7c92SJohn Birrell prm_direction = &rmsg->rm_direction; 186102c7c92SJohn Birrell prp_stat = &rmsg->rm_reply.rp_stat; 187102c7c92SJohn Birrell 18899064799SGarrett Wollman if ( 18939f37784SPeter Wemm xdr_u_int32_t(xdrs, &(rmsg->rm_xid)) && 190102c7c92SJohn Birrell xdr_enum(xdrs, (enum_t *) prm_direction) && 19199064799SGarrett Wollman (rmsg->rm_direction == REPLY) ) 192102c7c92SJohn Birrell return (xdr_union(xdrs, (enum_t *) prp_stat, 1938360efbdSAlfred Perlstein (caddr_t)(void *)&(rmsg->rm_reply.ru), reply_dscrm, 1948360efbdSAlfred Perlstein NULL_xdrproc_t)); 19599064799SGarrett Wollman return (FALSE); 19699064799SGarrett Wollman } 19799064799SGarrett Wollman 19899064799SGarrett Wollman 19999064799SGarrett Wollman /* 20099064799SGarrett Wollman * Serializes the "static part" of a call message header. 20199064799SGarrett Wollman * The fields include: rm_xid, rm_direction, rpcvers, prog, and vers. 20299064799SGarrett Wollman * The rm_xid is not really static, but the user can easily munge on the fly. 20399064799SGarrett Wollman */ 20499064799SGarrett Wollman bool_t 205*a7c2cd38SCraig Rodrigues xdr_callhdr(XDR *xdrs, struct rpc_msg *cmsg) 20699064799SGarrett Wollman { 207102c7c92SJohn Birrell enum msg_type *prm_direction; 20899064799SGarrett Wollman 2098360efbdSAlfred Perlstein assert(xdrs != NULL); 2108360efbdSAlfred Perlstein assert(cmsg != NULL); 2118360efbdSAlfred Perlstein 212102c7c92SJohn Birrell prm_direction = &cmsg->rm_direction; 213102c7c92SJohn Birrell 21499064799SGarrett Wollman cmsg->rm_direction = CALL; 21599064799SGarrett Wollman cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION; 21699064799SGarrett Wollman if ( 21799064799SGarrett Wollman (xdrs->x_op == XDR_ENCODE) && 21839f37784SPeter Wemm xdr_u_int32_t(xdrs, &(cmsg->rm_xid)) && 219102c7c92SJohn Birrell xdr_enum(xdrs, (enum_t *) prm_direction) && 22039f37784SPeter Wemm xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_rpcvers)) && 22139f37784SPeter Wemm xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_prog)) ) 22239f37784SPeter Wemm return (xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_vers))); 22399064799SGarrett Wollman return (FALSE); 22499064799SGarrett Wollman } 22599064799SGarrett Wollman 22699064799SGarrett Wollman /* ************************** Client utility routine ************* */ 22799064799SGarrett Wollman 22899064799SGarrett Wollman static void 229*a7c2cd38SCraig Rodrigues accepted(enum accept_stat acpt_stat, struct rpc_err *error) 23099064799SGarrett Wollman { 23199064799SGarrett Wollman 2328360efbdSAlfred Perlstein assert(error != NULL); 2338360efbdSAlfred Perlstein 23499064799SGarrett Wollman switch (acpt_stat) { 23599064799SGarrett Wollman 23699064799SGarrett Wollman case PROG_UNAVAIL: 23799064799SGarrett Wollman error->re_status = RPC_PROGUNAVAIL; 23899064799SGarrett Wollman return; 23999064799SGarrett Wollman 24099064799SGarrett Wollman case PROG_MISMATCH: 24199064799SGarrett Wollman error->re_status = RPC_PROGVERSMISMATCH; 24299064799SGarrett Wollman return; 24399064799SGarrett Wollman 24499064799SGarrett Wollman case PROC_UNAVAIL: 24599064799SGarrett Wollman error->re_status = RPC_PROCUNAVAIL; 24699064799SGarrett Wollman return; 24799064799SGarrett Wollman 24899064799SGarrett Wollman case GARBAGE_ARGS: 24999064799SGarrett Wollman error->re_status = RPC_CANTDECODEARGS; 25099064799SGarrett Wollman return; 25199064799SGarrett Wollman 25299064799SGarrett Wollman case SYSTEM_ERR: 25399064799SGarrett Wollman error->re_status = RPC_SYSTEMERROR; 25499064799SGarrett Wollman return; 25599064799SGarrett Wollman 25699064799SGarrett Wollman case SUCCESS: 25799064799SGarrett Wollman error->re_status = RPC_SUCCESS; 25899064799SGarrett Wollman return; 25999064799SGarrett Wollman } 2608360efbdSAlfred Perlstein /* NOTREACHED */ 26199064799SGarrett Wollman /* something's wrong, but we don't know what ... */ 26299064799SGarrett Wollman error->re_status = RPC_FAILED; 2638360efbdSAlfred Perlstein error->re_lb.s1 = (int32_t)MSG_ACCEPTED; 2648360efbdSAlfred Perlstein error->re_lb.s2 = (int32_t)acpt_stat; 26599064799SGarrett Wollman } 26699064799SGarrett Wollman 26799064799SGarrett Wollman static void 26899064799SGarrett Wollman rejected(rjct_stat, error) 2698360efbdSAlfred Perlstein enum reject_stat rjct_stat; 2708360efbdSAlfred Perlstein struct rpc_err *error; 27199064799SGarrett Wollman { 27299064799SGarrett Wollman 2738360efbdSAlfred Perlstein assert(error != NULL); 27499064799SGarrett Wollman 2758360efbdSAlfred Perlstein switch (rjct_stat) { 2768360efbdSAlfred Perlstein case RPC_MISMATCH: 27799064799SGarrett Wollman error->re_status = RPC_VERSMISMATCH; 27899064799SGarrett Wollman return; 27999064799SGarrett Wollman 28099064799SGarrett Wollman case AUTH_ERROR: 28199064799SGarrett Wollman error->re_status = RPC_AUTHERROR; 28299064799SGarrett Wollman return; 28399064799SGarrett Wollman } 28499064799SGarrett Wollman /* something's wrong, but we don't know what ... */ 2858360efbdSAlfred Perlstein /* NOTREACHED */ 28699064799SGarrett Wollman error->re_status = RPC_FAILED; 2878360efbdSAlfred Perlstein error->re_lb.s1 = (int32_t)MSG_DENIED; 2888360efbdSAlfred Perlstein error->re_lb.s2 = (int32_t)rjct_stat; 28999064799SGarrett Wollman } 29099064799SGarrett Wollman 29199064799SGarrett Wollman /* 29299064799SGarrett Wollman * given a reply message, fills in the error 29399064799SGarrett Wollman */ 29499064799SGarrett Wollman void 29599064799SGarrett Wollman _seterr_reply(msg, error) 2968360efbdSAlfred Perlstein struct rpc_msg *msg; 2978360efbdSAlfred Perlstein struct rpc_err *error; 29899064799SGarrett Wollman { 29999064799SGarrett Wollman 3008360efbdSAlfred Perlstein assert(msg != NULL); 3018360efbdSAlfred Perlstein assert(error != NULL); 3028360efbdSAlfred Perlstein 30399064799SGarrett Wollman /* optimized for normal, SUCCESSful case */ 30499064799SGarrett Wollman switch (msg->rm_reply.rp_stat) { 30599064799SGarrett Wollman 30699064799SGarrett Wollman case MSG_ACCEPTED: 30799064799SGarrett Wollman if (msg->acpted_rply.ar_stat == SUCCESS) { 30899064799SGarrett Wollman error->re_status = RPC_SUCCESS; 30999064799SGarrett Wollman return; 3108360efbdSAlfred Perlstein } 31199064799SGarrett Wollman accepted(msg->acpted_rply.ar_stat, error); 31299064799SGarrett Wollman break; 31399064799SGarrett Wollman 31499064799SGarrett Wollman case MSG_DENIED: 31599064799SGarrett Wollman rejected(msg->rjcted_rply.rj_stat, error); 31699064799SGarrett Wollman break; 31799064799SGarrett Wollman 31899064799SGarrett Wollman default: 31999064799SGarrett Wollman error->re_status = RPC_FAILED; 3208360efbdSAlfred Perlstein error->re_lb.s1 = (int32_t)(msg->rm_reply.rp_stat); 32199064799SGarrett Wollman break; 32299064799SGarrett Wollman } 32399064799SGarrett Wollman switch (error->re_status) { 32499064799SGarrett Wollman 32599064799SGarrett Wollman case RPC_VERSMISMATCH: 32699064799SGarrett Wollman error->re_vers.low = msg->rjcted_rply.rj_vers.low; 32799064799SGarrett Wollman error->re_vers.high = msg->rjcted_rply.rj_vers.high; 32899064799SGarrett Wollman break; 32999064799SGarrett Wollman 33099064799SGarrett Wollman case RPC_AUTHERROR: 33199064799SGarrett Wollman error->re_why = msg->rjcted_rply.rj_why; 33299064799SGarrett Wollman break; 33399064799SGarrett Wollman 33499064799SGarrett Wollman case RPC_PROGVERSMISMATCH: 33599064799SGarrett Wollman error->re_vers.low = msg->acpted_rply.ar_vers.low; 33699064799SGarrett Wollman error->re_vers.high = msg->acpted_rply.ar_vers.high; 33799064799SGarrett Wollman break; 3388360efbdSAlfred Perlstein 3398360efbdSAlfred Perlstein case RPC_FAILED: 3408360efbdSAlfred Perlstein case RPC_SUCCESS: 3418360efbdSAlfred Perlstein case RPC_PROGNOTREGISTERED: 3428360efbdSAlfred Perlstein case RPC_PMAPFAILURE: 3438360efbdSAlfred Perlstein case RPC_UNKNOWNPROTO: 3448360efbdSAlfred Perlstein case RPC_UNKNOWNHOST: 3458360efbdSAlfred Perlstein case RPC_SYSTEMERROR: 3468360efbdSAlfred Perlstein case RPC_CANTDECODEARGS: 3478360efbdSAlfred Perlstein case RPC_PROCUNAVAIL: 3488360efbdSAlfred Perlstein case RPC_PROGUNAVAIL: 3498360efbdSAlfred Perlstein case RPC_TIMEDOUT: 3508360efbdSAlfred Perlstein case RPC_CANTRECV: 3518360efbdSAlfred Perlstein case RPC_CANTSEND: 3528360efbdSAlfred Perlstein case RPC_CANTDECODERES: 3538360efbdSAlfred Perlstein case RPC_CANTENCODEARGS: 354f12d1a5dSJames Raynard default: 355f12d1a5dSJames Raynard break; 35699064799SGarrett Wollman } 35799064799SGarrett Wollman } 358