174462Salfred/*	$NetBSD: rpc_prot.c,v 1.16 2000/06/02 23:11:13 fvdl Exp $	*/
274462Salfred
3261046Smav/*-
4261046Smav * Copyright (c) 2009, Sun Microsystems, Inc.
5261046Smav * All rights reserved.
68870Srgrimes *
7261046Smav * Redistribution and use in source and binary forms, with or without
8261046Smav * modification, are permitted provided that the following conditions are met:
9261046Smav * - Redistributions of source code must retain the above copyright notice,
10261046Smav *   this list of conditions and the following disclaimer.
11261046Smav * - Redistributions in binary form must reproduce the above copyright notice,
12261046Smav *   this list of conditions and the following disclaimer in the documentation
13261046Smav *   and/or other materials provided with the distribution.
14261046Smav * - Neither the name of Sun Microsystems, Inc. nor the names of its
15261046Smav *   contributors may be used to endorse or promote products derived
16261046Smav *   from this software without specific prior written permission.
17261046Smav *
18261046Smav * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19261046Smav * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20261046Smav * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21261046Smav * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22261046Smav * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23261046Smav * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24261046Smav * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25261046Smav * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26261046Smav * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27261046Smav * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28261046Smav * 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: stable/10/lib/libc/rpc/rpc_prot.c 309494 2016-12-03 18:17:06Z ngie $");
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
71309494Sngiexdr_opaque_auth(XDR *xdrs, struct opaque_auth *ap)
721901Swollman{
731901Swollman
7474462Salfred	assert(xdrs != NULL);
7574462Salfred	assert(ap != NULL);
7674462Salfred
771901Swollman	if (xdr_enum(xdrs, &(ap->oa_flavor)))
781901Swollman		return (xdr_bytes(xdrs, &ap->oa_base,
791901Swollman			&ap->oa_length, MAX_AUTH_BYTES));
801901Swollman	return (FALSE);
811901Swollman}
821901Swollman
831901Swollman/*
841901Swollman * XDR a DES block
851901Swollman */
861901Swollmanbool_t
87309494Sngiexdr_des_block(XDR *xdrs, des_block *blkp)
881901Swollman{
8974462Salfred
9074462Salfred	assert(xdrs != NULL);
9174462Salfred	assert(blkp != NULL);
9274462Salfred
9374462Salfred	return (xdr_opaque(xdrs, (caddr_t)(void *)blkp, sizeof(des_block)));
941901Swollman}
951901Swollman
961901Swollman/* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */
971901Swollman
981901Swollman/*
991901Swollman * XDR the MSG_ACCEPTED part of a reply message union
1001901Swollman */
1018870Srgrimesbool_t
102309494Sngiexdr_accepted_reply(XDR *xdrs, struct accepted_reply *ar)
1031901Swollman{
104173763Sjb	enum accept_stat *par_stat;
1051901Swollman
10674462Salfred	assert(xdrs != NULL);
10774462Salfred	assert(ar != NULL);
10874462Salfred
109173763Sjb	par_stat = &ar->ar_stat;
110173763Sjb
1111901Swollman	/* personalized union, rather than calling xdr_union */
1121901Swollman	if (! xdr_opaque_auth(xdrs, &(ar->ar_verf)))
1131901Swollman		return (FALSE);
114173763Sjb	if (! xdr_enum(xdrs, (enum_t *) par_stat))
1151901Swollman		return (FALSE);
1161901Swollman	switch (ar->ar_stat) {
1171901Swollman
1181901Swollman	case SUCCESS:
1191901Swollman		return ((*(ar->ar_results.proc))(xdrs, ar->ar_results.where));
1201901Swollman
1211901Swollman	case PROG_MISMATCH:
122309493Sngie		if (!xdr_rpcvers(xdrs, &(ar->ar_vers.low)))
1231901Swollman			return (FALSE);
124309493Sngie		return (xdr_rpcvers(xdrs, &(ar->ar_vers.high)));
12574462Salfred
12674462Salfred	case GARBAGE_ARGS:
12774462Salfred	case SYSTEM_ERR:
12874462Salfred	case PROC_UNAVAIL:
12974462Salfred	case PROG_UNAVAIL:
13016283Sjraynard		break;
1311901Swollman	}
1321901Swollman	return (TRUE);  /* TRUE => open ended set of problems */
1331901Swollman}
1341901Swollman
1351901Swollman/*
1361901Swollman * XDR the MSG_DENIED part of a reply message union
1371901Swollman */
13874462Salfredbool_t
139309494Sngiexdr_rejected_reply(XDR *xdrs, struct rejected_reply *rr)
1401901Swollman{
141173763Sjb	enum reject_stat *prj_stat;
142173763Sjb	enum auth_stat *prj_why;
1431901Swollman
14474462Salfred	assert(xdrs != NULL);
14574462Salfred	assert(rr != NULL);
14674462Salfred
147173763Sjb	prj_stat = &rr->rj_stat;
148173763Sjb
1491901Swollman	/* personalized union, rather than calling xdr_union */
150173763Sjb	if (! xdr_enum(xdrs, (enum_t *) prj_stat))
1511901Swollman		return (FALSE);
1521901Swollman	switch (rr->rj_stat) {
1531901Swollman
1541901Swollman	case RPC_MISMATCH:
155309493Sngie		if (! xdr_rpcvers(xdrs, &(rr->rj_vers.low)))
1561901Swollman			return (FALSE);
157309493Sngie		return (xdr_rpcvers(xdrs, &(rr->rj_vers.high)));
1581901Swollman
1591901Swollman	case AUTH_ERROR:
160173763Sjb		prj_why = &rr->rj_why;
161173763Sjb		return (xdr_enum(xdrs, (enum_t *) prj_why));
1621901Swollman	}
16374462Salfred	/* NOTREACHED */
16474462Salfred	assert(0);
1651901Swollman	return (FALSE);
1661901Swollman}
1671901Swollman
16874462Salfredstatic const struct xdr_discrim reply_dscrm[3] = {
16974462Salfred	{ (int)MSG_ACCEPTED, (xdrproc_t)xdr_accepted_reply },
17074462Salfred	{ (int)MSG_DENIED, (xdrproc_t)xdr_rejected_reply },
1711901Swollman	{ __dontcare__, NULL_xdrproc_t } };
1721901Swollman
1731901Swollman/*
1741901Swollman * XDR a reply message
1751901Swollman */
1761901Swollmanbool_t
177309494Sngiexdr_replymsg(XDR *xdrs, struct rpc_msg *rmsg)
1781901Swollman{
179173763Sjb	enum msg_type *prm_direction;
180173763Sjb	enum reply_stat *prp_stat;
181173763Sjb
18274462Salfred	assert(xdrs != NULL);
18374462Salfred	assert(rmsg != NULL);
18474462Salfred
185173763Sjb	prm_direction = &rmsg->rm_direction;
186173763Sjb	prp_stat = &rmsg->rm_reply.rp_stat;
187173763Sjb
1881901Swollman	if (
18974462Salfred	    xdr_u_int32_t(xdrs, &(rmsg->rm_xid)) &&
190173763Sjb	    xdr_enum(xdrs, (enum_t *) prm_direction) &&
1911901Swollman	    (rmsg->rm_direction == REPLY) )
192173763Sjb		return (xdr_union(xdrs, (enum_t *) prp_stat,
19374462Salfred		   (caddr_t)(void *)&(rmsg->rm_reply.ru), reply_dscrm,
19474462Salfred		   NULL_xdrproc_t));
1951901Swollman	return (FALSE);
1961901Swollman}
1971901Swollman
1981901Swollman
1991901Swollman/*
2001901Swollman * Serializes the "static part" of a call message header.
2011901Swollman * The fields include: rm_xid, rm_direction, rpcvers, prog, and vers.
2021901Swollman * The rm_xid is not really static, but the user can easily munge on the fly.
2031901Swollman */
2041901Swollmanbool_t
205309494Sngiexdr_callhdr(XDR *xdrs, struct rpc_msg *cmsg)
2061901Swollman{
207173763Sjb	enum msg_type *prm_direction;
2081901Swollman
20974462Salfred	assert(xdrs != NULL);
21074462Salfred	assert(cmsg != NULL);
21174462Salfred
212173763Sjb	prm_direction = &cmsg->rm_direction;
213173763Sjb
2141901Swollman	cmsg->rm_direction = CALL;
2151901Swollman	cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION;
2161901Swollman	if (
2171901Swollman	    (xdrs->x_op == XDR_ENCODE) &&
21821086Speter	    xdr_u_int32_t(xdrs, &(cmsg->rm_xid)) &&
219173763Sjb	    xdr_enum(xdrs, (enum_t *) prm_direction) &&
220309493Sngie	    xdr_rpcvers(xdrs, &(cmsg->rm_call.cb_rpcvers)) &&
221309493Sngie	    xdr_rpcprog(xdrs, &(cmsg->rm_call.cb_prog)) )
22274462Salfred		return (xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_vers)));
2231901Swollman	return (FALSE);
2241901Swollman}
2251901Swollman
2261901Swollman/* ************************** Client utility routine ************* */
2271901Swollman
2281901Swollmanstatic void
229309494Sngieaccepted(enum accept_stat acpt_stat, struct rpc_err *error)
2301901Swollman{
2311901Swollman
23274462Salfred	assert(error != NULL);
23374462Salfred
2341901Swollman	switch (acpt_stat) {
2351901Swollman
2361901Swollman	case PROG_UNAVAIL:
2371901Swollman		error->re_status = RPC_PROGUNAVAIL;
2381901Swollman		return;
2391901Swollman
2401901Swollman	case PROG_MISMATCH:
2411901Swollman		error->re_status = RPC_PROGVERSMISMATCH;
2421901Swollman		return;
2431901Swollman
2441901Swollman	case PROC_UNAVAIL:
2451901Swollman		error->re_status = RPC_PROCUNAVAIL;
2461901Swollman		return;
2471901Swollman
2481901Swollman	case GARBAGE_ARGS:
2491901Swollman		error->re_status = RPC_CANTDECODEARGS;
2501901Swollman		return;
2511901Swollman
2521901Swollman	case SYSTEM_ERR:
2531901Swollman		error->re_status = RPC_SYSTEMERROR;
2541901Swollman		return;
2551901Swollman
2561901Swollman	case SUCCESS:
2571901Swollman		error->re_status = RPC_SUCCESS;
2581901Swollman		return;
2591901Swollman	}
26074462Salfred	/* NOTREACHED */
2611901Swollman	/* something's wrong, but we don't know what ... */
2621901Swollman	error->re_status = RPC_FAILED;
26374462Salfred	error->re_lb.s1 = (int32_t)MSG_ACCEPTED;
26474462Salfred	error->re_lb.s2 = (int32_t)acpt_stat;
2651901Swollman}
2661901Swollman
26774462Salfredstatic void
268309487Sngierejected(enum reject_stat rjct_stat, struct rpc_err *error)
2691901Swollman{
2701901Swollman
27174462Salfred	assert(error != NULL);
27274462Salfred
2731901Swollman	switch (rjct_stat) {
27474462Salfred	case RPC_MISMATCH:
2751901Swollman		error->re_status = RPC_VERSMISMATCH;
2761901Swollman		return;
2771901Swollman
2781901Swollman	case AUTH_ERROR:
2791901Swollman		error->re_status = RPC_AUTHERROR;
2801901Swollman		return;
2811901Swollman	}
2821901Swollman	/* something's wrong, but we don't know what ... */
28374462Salfred	/* NOTREACHED */
2841901Swollman	error->re_status = RPC_FAILED;
28574462Salfred	error->re_lb.s1 = (int32_t)MSG_DENIED;
28674462Salfred	error->re_lb.s2 = (int32_t)rjct_stat;
2871901Swollman}
2881901Swollman
2891901Swollman/*
2901901Swollman * given a reply message, fills in the error
2911901Swollman */
2921901Swollmanvoid
293309487Sngie_seterr_reply(struct rpc_msg *msg, struct rpc_err *error)
2941901Swollman{
2951901Swollman
29674462Salfred	assert(msg != NULL);
29774462Salfred	assert(error != NULL);
29874462Salfred
2991901Swollman	/* optimized for normal, SUCCESSful case */
3001901Swollman	switch (msg->rm_reply.rp_stat) {
3011901Swollman
3021901Swollman	case MSG_ACCEPTED:
3031901Swollman		if (msg->acpted_rply.ar_stat == SUCCESS) {
3041901Swollman			error->re_status = RPC_SUCCESS;
3051901Swollman			return;
30674462Salfred		}
3071901Swollman		accepted(msg->acpted_rply.ar_stat, error);
3081901Swollman		break;
3091901Swollman
3101901Swollman	case MSG_DENIED:
3111901Swollman		rejected(msg->rjcted_rply.rj_stat, error);
3121901Swollman		break;
3131901Swollman
3141901Swollman	default:
3151901Swollman		error->re_status = RPC_FAILED;
31674462Salfred		error->re_lb.s1 = (int32_t)(msg->rm_reply.rp_stat);
3171901Swollman		break;
3181901Swollman	}
3191901Swollman	switch (error->re_status) {
3201901Swollman
3211901Swollman	case RPC_VERSMISMATCH:
3221901Swollman		error->re_vers.low = msg->rjcted_rply.rj_vers.low;
3231901Swollman		error->re_vers.high = msg->rjcted_rply.rj_vers.high;
3241901Swollman		break;
3251901Swollman
3261901Swollman	case RPC_AUTHERROR:
3271901Swollman		error->re_why = msg->rjcted_rply.rj_why;
3281901Swollman		break;
3291901Swollman
3301901Swollman	case RPC_PROGVERSMISMATCH:
3311901Swollman		error->re_vers.low = msg->acpted_rply.ar_vers.low;
3321901Swollman		error->re_vers.high = msg->acpted_rply.ar_vers.high;
3331901Swollman		break;
33474462Salfred
33574462Salfred	case RPC_FAILED:
33674462Salfred	case RPC_SUCCESS:
33774462Salfred	case RPC_PROGNOTREGISTERED:
33874462Salfred	case RPC_PMAPFAILURE:
33974462Salfred	case RPC_UNKNOWNPROTO:
34074462Salfred	case RPC_UNKNOWNHOST:
34174462Salfred	case RPC_SYSTEMERROR:
34274462Salfred	case RPC_CANTDECODEARGS:
34374462Salfred	case RPC_PROCUNAVAIL:
34474462Salfred	case RPC_PROGUNAVAIL:
34574462Salfred	case RPC_TIMEDOUT:
34674462Salfred	case RPC_CANTRECV:
34774462Salfred	case RPC_CANTSEND:
34874462Salfred	case RPC_CANTDECODERES:
34974462Salfred	case RPC_CANTENCODEARGS:
35016283Sjraynard	default:
35116283Sjraynard		break;
3521901Swollman	}
3531901Swollman}
354