174462Salfred/* $NetBSD: rpc_prot.c,v 1.16 2000/06/02 23:11:13 fvdl Exp $ */ 274462Salfred 3261057Smav/*- 4261057Smav * Copyright (c) 2009, Sun Microsystems, Inc. 5261057Smav * All rights reserved. 68870Srgrimes * 7261057Smav * Redistribution and use in source and binary forms, with or without 8261057Smav * modification, are permitted provided that the following conditions are met: 9261057Smav * - Redistributions of source code must retain the above copyright notice, 10261057Smav * this list of conditions and the following disclaimer. 11261057Smav * - Redistributions in binary form must reproduce the above copyright notice, 12261057Smav * this list of conditions and the following disclaimer in the documentation 13261057Smav * and/or other materials provided with the distribution. 14261057Smav * - Neither the name of Sun Microsystems, Inc. nor the names of its 15261057Smav * contributors may be used to endorse or promote products derived 16261057Smav * from this software without specific prior written permission. 17261057Smav * 18261057Smav * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19261057Smav * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20261057Smav * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21261057Smav * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22261057Smav * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23261057Smav * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24261057Smav * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25261057Smav * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26261057Smav * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27261057Smav * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28261057Smav * POSSIBILITY OF SUCH DAMAGE. 291901Swollman */ 301901Swollman 311901Swollman#if defined(LIBC_SCCS) && !defined(lint) 32136581Sobrienstatic char *sccsid2 = "@(#)rpc_prot.c 1.36 87/08/11 Copyr 1984 Sun Micro"; 3374462Salfredstatic char *sccsid = "@(#)rpc_prot.c 2.3 88/08/07 4.0 RPCSRC"; 341901Swollman#endif 3592990Sobrien#include <sys/cdefs.h> 3692990Sobrien__FBSDID("$FreeBSD$"); 371901Swollman 381901Swollman/* 391901Swollman * rpc_prot.c 401901Swollman * 411901Swollman * Copyright (C) 1984, Sun Microsystems, Inc. 421901Swollman * 431901Swollman * This set of routines implements the rpc message definition, 441901Swollman * its serializer and some common rpc utility routines. 451901Swollman * The routines are meant for various implementations of rpc - 461901Swollman * they are NOT for the rpc client or rpc service implementations! 471901Swollman * Because authentication stuff is easy and is part of rpc, the opaque 481901Swollman * routines are also in this program. 491901Swollman */ 501901Swollman 5174462Salfred#include "namespace.h" 521901Swollman#include <sys/param.h> 531901Swollman 5474462Salfred#include <assert.h> 5574462Salfred 561901Swollman#include <rpc/rpc.h> 5774462Salfred#include "un-namespace.h" 581901Swollman 5992905Sobrienstatic void accepted(enum accept_stat, struct rpc_err *); 6092905Sobrienstatic void rejected(enum reject_stat, struct rpc_err *); 6174462Salfred 621901Swollman/* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */ 631901Swollman 6474462Salfredextern struct opaque_auth _null_auth; 651901Swollman 661901Swollman/* 671901Swollman * XDR an opaque authentication struct 681901Swollman * (see auth.h) 691901Swollman */ 701901Swollmanbool_t 711901Swollmanxdr_opaque_auth(xdrs, ap) 7274462Salfred XDR *xdrs; 7374462Salfred struct opaque_auth *ap; 741901Swollman{ 751901Swollman 7674462Salfred assert(xdrs != NULL); 7774462Salfred assert(ap != NULL); 7874462Salfred 791901Swollman if (xdr_enum(xdrs, &(ap->oa_flavor))) 801901Swollman return (xdr_bytes(xdrs, &ap->oa_base, 811901Swollman &ap->oa_length, MAX_AUTH_BYTES)); 821901Swollman return (FALSE); 831901Swollman} 841901Swollman 851901Swollman/* 861901Swollman * XDR a DES block 871901Swollman */ 881901Swollmanbool_t 891901Swollmanxdr_des_block(xdrs, blkp) 9074462Salfred XDR *xdrs; 9174462Salfred des_block *blkp; 921901Swollman{ 9374462Salfred 9474462Salfred assert(xdrs != NULL); 9574462Salfred assert(blkp != NULL); 9674462Salfred 9774462Salfred return (xdr_opaque(xdrs, (caddr_t)(void *)blkp, sizeof(des_block))); 981901Swollman} 991901Swollman 1001901Swollman/* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */ 1011901Swollman 1021901Swollman/* 1031901Swollman * XDR the MSG_ACCEPTED part of a reply message union 1041901Swollman */ 1058870Srgrimesbool_t 1061901Swollmanxdr_accepted_reply(xdrs, ar) 10774462Salfred XDR *xdrs; 10874462Salfred struct accepted_reply *ar; 1091901Swollman{ 110173763Sjb enum accept_stat *par_stat; 1111901Swollman 11274462Salfred assert(xdrs != NULL); 11374462Salfred assert(ar != NULL); 11474462Salfred 115173763Sjb par_stat = &ar->ar_stat; 116173763Sjb 1171901Swollman /* personalized union, rather than calling xdr_union */ 1181901Swollman if (! xdr_opaque_auth(xdrs, &(ar->ar_verf))) 1191901Swollman return (FALSE); 120173763Sjb if (! xdr_enum(xdrs, (enum_t *) par_stat)) 1211901Swollman return (FALSE); 1221901Swollman switch (ar->ar_stat) { 1231901Swollman 1241901Swollman case SUCCESS: 1251901Swollman return ((*(ar->ar_results.proc))(xdrs, ar->ar_results.where)); 1261901Swollman 1271901Swollman case PROG_MISMATCH: 12821086Speter if (! xdr_u_int32_t(xdrs, &(ar->ar_vers.low))) 1291901Swollman return (FALSE); 13021086Speter return (xdr_u_int32_t(xdrs, &(ar->ar_vers.high))); 13174462Salfred 13274462Salfred case GARBAGE_ARGS: 13374462Salfred case SYSTEM_ERR: 13474462Salfred case PROC_UNAVAIL: 13574462Salfred case PROG_UNAVAIL: 13616283Sjraynard break; 1371901Swollman } 1381901Swollman return (TRUE); /* TRUE => open ended set of problems */ 1391901Swollman} 1401901Swollman 1411901Swollman/* 1421901Swollman * XDR the MSG_DENIED part of a reply message union 1431901Swollman */ 14474462Salfredbool_t 1451901Swollmanxdr_rejected_reply(xdrs, rr) 14674462Salfred XDR *xdrs; 14774462Salfred struct rejected_reply *rr; 1481901Swollman{ 149173763Sjb enum reject_stat *prj_stat; 150173763Sjb enum auth_stat *prj_why; 1511901Swollman 15274462Salfred assert(xdrs != NULL); 15374462Salfred assert(rr != NULL); 15474462Salfred 155173763Sjb prj_stat = &rr->rj_stat; 156173763Sjb 1571901Swollman /* personalized union, rather than calling xdr_union */ 158173763Sjb if (! xdr_enum(xdrs, (enum_t *) prj_stat)) 1591901Swollman return (FALSE); 1601901Swollman switch (rr->rj_stat) { 1611901Swollman 1621901Swollman case RPC_MISMATCH: 16321086Speter if (! xdr_u_int32_t(xdrs, &(rr->rj_vers.low))) 1641901Swollman return (FALSE); 16521086Speter return (xdr_u_int32_t(xdrs, &(rr->rj_vers.high))); 1661901Swollman 1671901Swollman case AUTH_ERROR: 168173763Sjb prj_why = &rr->rj_why; 169173763Sjb return (xdr_enum(xdrs, (enum_t *) prj_why)); 1701901Swollman } 17174462Salfred /* NOTREACHED */ 17274462Salfred assert(0); 1731901Swollman return (FALSE); 1741901Swollman} 1751901Swollman 17674462Salfredstatic const struct xdr_discrim reply_dscrm[3] = { 17774462Salfred { (int)MSG_ACCEPTED, (xdrproc_t)xdr_accepted_reply }, 17874462Salfred { (int)MSG_DENIED, (xdrproc_t)xdr_rejected_reply }, 1791901Swollman { __dontcare__, NULL_xdrproc_t } }; 1801901Swollman 1811901Swollman/* 1821901Swollman * XDR a reply message 1831901Swollman */ 1841901Swollmanbool_t 1851901Swollmanxdr_replymsg(xdrs, rmsg) 18674462Salfred XDR *xdrs; 18774462Salfred struct rpc_msg *rmsg; 1881901Swollman{ 189173763Sjb enum msg_type *prm_direction; 190173763Sjb enum reply_stat *prp_stat; 191173763Sjb 19274462Salfred assert(xdrs != NULL); 19374462Salfred assert(rmsg != NULL); 19474462Salfred 195173763Sjb prm_direction = &rmsg->rm_direction; 196173763Sjb prp_stat = &rmsg->rm_reply.rp_stat; 197173763Sjb 1981901Swollman if ( 19974462Salfred xdr_u_int32_t(xdrs, &(rmsg->rm_xid)) && 200173763Sjb xdr_enum(xdrs, (enum_t *) prm_direction) && 2011901Swollman (rmsg->rm_direction == REPLY) ) 202173763Sjb return (xdr_union(xdrs, (enum_t *) prp_stat, 20374462Salfred (caddr_t)(void *)&(rmsg->rm_reply.ru), reply_dscrm, 20474462Salfred NULL_xdrproc_t)); 2051901Swollman return (FALSE); 2061901Swollman} 2071901Swollman 2081901Swollman 2091901Swollman/* 2101901Swollman * Serializes the "static part" of a call message header. 2111901Swollman * The fields include: rm_xid, rm_direction, rpcvers, prog, and vers. 2121901Swollman * The rm_xid is not really static, but the user can easily munge on the fly. 2131901Swollman */ 2141901Swollmanbool_t 2151901Swollmanxdr_callhdr(xdrs, cmsg) 21674462Salfred XDR *xdrs; 21774462Salfred struct rpc_msg *cmsg; 2181901Swollman{ 219173763Sjb enum msg_type *prm_direction; 2201901Swollman 22174462Salfred assert(xdrs != NULL); 22274462Salfred assert(cmsg != NULL); 22374462Salfred 224173763Sjb prm_direction = &cmsg->rm_direction; 225173763Sjb 2261901Swollman cmsg->rm_direction = CALL; 2271901Swollman cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION; 2281901Swollman if ( 2291901Swollman (xdrs->x_op == XDR_ENCODE) && 23021086Speter xdr_u_int32_t(xdrs, &(cmsg->rm_xid)) && 231173763Sjb xdr_enum(xdrs, (enum_t *) prm_direction) && 23221086Speter xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_rpcvers)) && 23321086Speter xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_prog)) ) 23474462Salfred return (xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_vers))); 2351901Swollman return (FALSE); 2361901Swollman} 2371901Swollman 2381901Swollman/* ************************** Client utility routine ************* */ 2391901Swollman 2401901Swollmanstatic void 2411901Swollmanaccepted(acpt_stat, error) 24274462Salfred enum accept_stat acpt_stat; 24374462Salfred struct rpc_err *error; 2441901Swollman{ 2451901Swollman 24674462Salfred assert(error != NULL); 24774462Salfred 2481901Swollman switch (acpt_stat) { 2491901Swollman 2501901Swollman case PROG_UNAVAIL: 2511901Swollman error->re_status = RPC_PROGUNAVAIL; 2521901Swollman return; 2531901Swollman 2541901Swollman case PROG_MISMATCH: 2551901Swollman error->re_status = RPC_PROGVERSMISMATCH; 2561901Swollman return; 2571901Swollman 2581901Swollman case PROC_UNAVAIL: 2591901Swollman error->re_status = RPC_PROCUNAVAIL; 2601901Swollman return; 2611901Swollman 2621901Swollman case GARBAGE_ARGS: 2631901Swollman error->re_status = RPC_CANTDECODEARGS; 2641901Swollman return; 2651901Swollman 2661901Swollman case SYSTEM_ERR: 2671901Swollman error->re_status = RPC_SYSTEMERROR; 2681901Swollman return; 2691901Swollman 2701901Swollman case SUCCESS: 2711901Swollman error->re_status = RPC_SUCCESS; 2721901Swollman return; 2731901Swollman } 27474462Salfred /* NOTREACHED */ 2751901Swollman /* something's wrong, but we don't know what ... */ 2761901Swollman error->re_status = RPC_FAILED; 27774462Salfred error->re_lb.s1 = (int32_t)MSG_ACCEPTED; 27874462Salfred error->re_lb.s2 = (int32_t)acpt_stat; 2791901Swollman} 2801901Swollman 28174462Salfredstatic void 2821901Swollmanrejected(rjct_stat, error) 28374462Salfred enum reject_stat rjct_stat; 28474462Salfred struct rpc_err *error; 2851901Swollman{ 2861901Swollman 28774462Salfred assert(error != NULL); 28874462Salfred 2891901Swollman switch (rjct_stat) { 29074462Salfred case RPC_MISMATCH: 2911901Swollman error->re_status = RPC_VERSMISMATCH; 2921901Swollman return; 2931901Swollman 2941901Swollman case AUTH_ERROR: 2951901Swollman error->re_status = RPC_AUTHERROR; 2961901Swollman return; 2971901Swollman } 2981901Swollman /* something's wrong, but we don't know what ... */ 29974462Salfred /* NOTREACHED */ 3001901Swollman error->re_status = RPC_FAILED; 30174462Salfred error->re_lb.s1 = (int32_t)MSG_DENIED; 30274462Salfred error->re_lb.s2 = (int32_t)rjct_stat; 3031901Swollman} 3041901Swollman 3051901Swollman/* 3061901Swollman * given a reply message, fills in the error 3071901Swollman */ 3081901Swollmanvoid 3091901Swollman_seterr_reply(msg, error) 31074462Salfred struct rpc_msg *msg; 31174462Salfred struct rpc_err *error; 3121901Swollman{ 3131901Swollman 31474462Salfred assert(msg != NULL); 31574462Salfred assert(error != NULL); 31674462Salfred 3171901Swollman /* optimized for normal, SUCCESSful case */ 3181901Swollman switch (msg->rm_reply.rp_stat) { 3191901Swollman 3201901Swollman case MSG_ACCEPTED: 3211901Swollman if (msg->acpted_rply.ar_stat == SUCCESS) { 3221901Swollman error->re_status = RPC_SUCCESS; 3231901Swollman return; 32474462Salfred } 3251901Swollman accepted(msg->acpted_rply.ar_stat, error); 3261901Swollman break; 3271901Swollman 3281901Swollman case MSG_DENIED: 3291901Swollman rejected(msg->rjcted_rply.rj_stat, error); 3301901Swollman break; 3311901Swollman 3321901Swollman default: 3331901Swollman error->re_status = RPC_FAILED; 33474462Salfred error->re_lb.s1 = (int32_t)(msg->rm_reply.rp_stat); 3351901Swollman break; 3361901Swollman } 3371901Swollman switch (error->re_status) { 3381901Swollman 3391901Swollman case RPC_VERSMISMATCH: 3401901Swollman error->re_vers.low = msg->rjcted_rply.rj_vers.low; 3411901Swollman error->re_vers.high = msg->rjcted_rply.rj_vers.high; 3421901Swollman break; 3431901Swollman 3441901Swollman case RPC_AUTHERROR: 3451901Swollman error->re_why = msg->rjcted_rply.rj_why; 3461901Swollman break; 3471901Swollman 3481901Swollman case RPC_PROGVERSMISMATCH: 3491901Swollman error->re_vers.low = msg->acpted_rply.ar_vers.low; 3501901Swollman error->re_vers.high = msg->acpted_rply.ar_vers.high; 3511901Swollman break; 35274462Salfred 35374462Salfred case RPC_FAILED: 35474462Salfred case RPC_SUCCESS: 35574462Salfred case RPC_PROGNOTREGISTERED: 35674462Salfred case RPC_PMAPFAILURE: 35774462Salfred case RPC_UNKNOWNPROTO: 35874462Salfred case RPC_UNKNOWNHOST: 35974462Salfred case RPC_SYSTEMERROR: 36074462Salfred case RPC_CANTDECODEARGS: 36174462Salfred case RPC_PROCUNAVAIL: 36274462Salfred case RPC_PROGUNAVAIL: 36374462Salfred case RPC_TIMEDOUT: 36474462Salfred case RPC_CANTRECV: 36574462Salfred case RPC_CANTSEND: 36674462Salfred case RPC_CANTDECODERES: 36774462Salfred case RPC_CANTENCODEARGS: 36816283Sjraynard default: 36916283Sjraynard break; 3701901Swollman } 3711901Swollman} 372