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