18360efbdSAlfred Perlstein /* $NetBSD: rpc_prot.c,v 1.16 2000/06/02 23:11:13 fvdl Exp $ */
28360efbdSAlfred Perlstein
32e322d37SHiroki Sato /*-
4*8a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause
5*8a16b7a1SPedro F. Giffuni *
62e322d37SHiroki Sato * Copyright (c) 2009, Sun Microsystems, Inc.
72e322d37SHiroki Sato * All rights reserved.
899064799SGarrett Wollman *
92e322d37SHiroki Sato * Redistribution and use in source and binary forms, with or without
102e322d37SHiroki Sato * modification, are permitted provided that the following conditions are met:
112e322d37SHiroki Sato * - Redistributions of source code must retain the above copyright notice,
122e322d37SHiroki Sato * this list of conditions and the following disclaimer.
132e322d37SHiroki Sato * - Redistributions in binary form must reproduce the above copyright notice,
142e322d37SHiroki Sato * this list of conditions and the following disclaimer in the documentation
152e322d37SHiroki Sato * and/or other materials provided with the distribution.
162e322d37SHiroki Sato * - Neither the name of Sun Microsystems, Inc. nor the names of its
172e322d37SHiroki Sato * contributors may be used to endorse or promote products derived
182e322d37SHiroki Sato * from this software without specific prior written permission.
1999064799SGarrett Wollman *
202e322d37SHiroki Sato * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
212e322d37SHiroki Sato * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
222e322d37SHiroki Sato * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
232e322d37SHiroki Sato * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
242e322d37SHiroki Sato * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
252e322d37SHiroki Sato * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
262e322d37SHiroki Sato * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
272e322d37SHiroki Sato * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
282e322d37SHiroki Sato * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
292e322d37SHiroki Sato * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
302e322d37SHiroki Sato * POSSIBILITY OF SUCH DAMAGE.
3199064799SGarrett Wollman */
3299064799SGarrett Wollman
3399064799SGarrett Wollman /*
3499064799SGarrett Wollman * rpc_prot.c
3599064799SGarrett Wollman *
3699064799SGarrett Wollman * Copyright (C) 1984, Sun Microsystems, Inc.
3799064799SGarrett Wollman *
3899064799SGarrett Wollman * This set of routines implements the rpc message definition,
3999064799SGarrett Wollman * its serializer and some common rpc utility routines.
4099064799SGarrett Wollman * The routines are meant for various implementations of rpc -
4199064799SGarrett Wollman * they are NOT for the rpc client or rpc service implementations!
4299064799SGarrett Wollman * Because authentication stuff is easy and is part of rpc, the opaque
4399064799SGarrett Wollman * routines are also in this program.
4499064799SGarrett Wollman */
4599064799SGarrett Wollman
468360efbdSAlfred Perlstein #include "namespace.h"
4799064799SGarrett Wollman #include <sys/param.h>
4899064799SGarrett Wollman
498360efbdSAlfred Perlstein #include <assert.h>
508360efbdSAlfred Perlstein
5199064799SGarrett Wollman #include <rpc/rpc.h>
528360efbdSAlfred Perlstein #include "un-namespace.h"
538360efbdSAlfred Perlstein
54c05ac53bSDavid E. O'Brien static void accepted(enum accept_stat, struct rpc_err *);
55c05ac53bSDavid E. O'Brien static void rejected(enum reject_stat, struct rpc_err *);
5699064799SGarrett Wollman
5799064799SGarrett Wollman /* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */
5899064799SGarrett Wollman
598360efbdSAlfred Perlstein extern struct opaque_auth _null_auth;
6099064799SGarrett Wollman
6199064799SGarrett Wollman /*
6299064799SGarrett Wollman * XDR an opaque authentication struct
6399064799SGarrett Wollman * (see auth.h)
6499064799SGarrett Wollman */
6599064799SGarrett Wollman bool_t
xdr_opaque_auth(XDR * xdrs,struct opaque_auth * ap)66a7c2cd38SCraig Rodrigues xdr_opaque_auth(XDR *xdrs, struct opaque_auth *ap)
6799064799SGarrett Wollman {
6899064799SGarrett Wollman
698360efbdSAlfred Perlstein assert(xdrs != NULL);
708360efbdSAlfred Perlstein assert(ap != NULL);
718360efbdSAlfred Perlstein
7299064799SGarrett Wollman if (xdr_enum(xdrs, &(ap->oa_flavor)))
7399064799SGarrett Wollman return (xdr_bytes(xdrs, &ap->oa_base,
7499064799SGarrett Wollman &ap->oa_length, MAX_AUTH_BYTES));
7599064799SGarrett Wollman return (FALSE);
7699064799SGarrett Wollman }
7799064799SGarrett Wollman
7899064799SGarrett Wollman /*
7999064799SGarrett Wollman * XDR a DES block
8099064799SGarrett Wollman */
8199064799SGarrett Wollman bool_t
xdr_des_block(XDR * xdrs,des_block * blkp)82a7c2cd38SCraig Rodrigues xdr_des_block(XDR *xdrs, des_block *blkp)
8399064799SGarrett Wollman {
848360efbdSAlfred Perlstein
858360efbdSAlfred Perlstein assert(xdrs != NULL);
868360efbdSAlfred Perlstein assert(blkp != NULL);
878360efbdSAlfred Perlstein
888360efbdSAlfred Perlstein return (xdr_opaque(xdrs, (caddr_t)(void *)blkp, sizeof(des_block)));
8999064799SGarrett Wollman }
9099064799SGarrett Wollman
9199064799SGarrett Wollman /* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */
9299064799SGarrett Wollman
9399064799SGarrett Wollman /*
9499064799SGarrett Wollman * XDR the MSG_ACCEPTED part of a reply message union
9599064799SGarrett Wollman */
9699064799SGarrett Wollman bool_t
xdr_accepted_reply(XDR * xdrs,struct accepted_reply * ar)97a7c2cd38SCraig Rodrigues xdr_accepted_reply(XDR *xdrs, struct accepted_reply *ar)
9899064799SGarrett Wollman {
99102c7c92SJohn Birrell enum accept_stat *par_stat;
10099064799SGarrett Wollman
1018360efbdSAlfred Perlstein assert(xdrs != NULL);
1028360efbdSAlfred Perlstein assert(ar != NULL);
1038360efbdSAlfred Perlstein
104102c7c92SJohn Birrell par_stat = &ar->ar_stat;
105102c7c92SJohn Birrell
10699064799SGarrett Wollman /* personalized union, rather than calling xdr_union */
10799064799SGarrett Wollman if (! xdr_opaque_auth(xdrs, &(ar->ar_verf)))
10899064799SGarrett Wollman return (FALSE);
109102c7c92SJohn Birrell if (! xdr_enum(xdrs, (enum_t *) par_stat))
11099064799SGarrett Wollman return (FALSE);
11199064799SGarrett Wollman switch (ar->ar_stat) {
11299064799SGarrett Wollman
11399064799SGarrett Wollman case SUCCESS:
11499064799SGarrett Wollman return ((*(ar->ar_results.proc))(xdrs, ar->ar_results.where));
11599064799SGarrett Wollman
11699064799SGarrett Wollman case PROG_MISMATCH:
117478eb9e9SPedro F. Giffuni if (!xdr_rpcvers(xdrs, &(ar->ar_vers.low)))
11899064799SGarrett Wollman return (FALSE);
119478eb9e9SPedro F. Giffuni return (xdr_rpcvers(xdrs, &(ar->ar_vers.high)));
1208360efbdSAlfred Perlstein
1218360efbdSAlfred Perlstein case GARBAGE_ARGS:
1228360efbdSAlfred Perlstein case SYSTEM_ERR:
1238360efbdSAlfred Perlstein case PROC_UNAVAIL:
1248360efbdSAlfred Perlstein case PROG_UNAVAIL:
125f12d1a5dSJames Raynard break;
12699064799SGarrett Wollman }
12799064799SGarrett Wollman return (TRUE); /* TRUE => open ended set of problems */
12899064799SGarrett Wollman }
12999064799SGarrett Wollman
13099064799SGarrett Wollman /*
13199064799SGarrett Wollman * XDR the MSG_DENIED part of a reply message union
13299064799SGarrett Wollman */
13399064799SGarrett Wollman bool_t
xdr_rejected_reply(XDR * xdrs,struct rejected_reply * rr)134a7c2cd38SCraig Rodrigues xdr_rejected_reply(XDR *xdrs, struct rejected_reply *rr)
13599064799SGarrett Wollman {
136102c7c92SJohn Birrell enum reject_stat *prj_stat;
137102c7c92SJohn Birrell enum auth_stat *prj_why;
13899064799SGarrett Wollman
1398360efbdSAlfred Perlstein assert(xdrs != NULL);
1408360efbdSAlfred Perlstein assert(rr != NULL);
1418360efbdSAlfred Perlstein
142102c7c92SJohn Birrell prj_stat = &rr->rj_stat;
143102c7c92SJohn Birrell
14499064799SGarrett Wollman /* personalized union, rather than calling xdr_union */
145102c7c92SJohn Birrell if (! xdr_enum(xdrs, (enum_t *) prj_stat))
14699064799SGarrett Wollman return (FALSE);
14799064799SGarrett Wollman switch (rr->rj_stat) {
14899064799SGarrett Wollman
14999064799SGarrett Wollman case RPC_MISMATCH:
150478eb9e9SPedro F. Giffuni if (! xdr_rpcvers(xdrs, &(rr->rj_vers.low)))
15199064799SGarrett Wollman return (FALSE);
152478eb9e9SPedro F. Giffuni return (xdr_rpcvers(xdrs, &(rr->rj_vers.high)));
15399064799SGarrett Wollman
15499064799SGarrett Wollman case AUTH_ERROR:
155102c7c92SJohn Birrell prj_why = &rr->rj_why;
156102c7c92SJohn Birrell return (xdr_enum(xdrs, (enum_t *) prj_why));
15799064799SGarrett Wollman }
1588360efbdSAlfred Perlstein /* NOTREACHED */
1598360efbdSAlfred Perlstein assert(0);
16099064799SGarrett Wollman return (FALSE);
16199064799SGarrett Wollman }
16299064799SGarrett Wollman
1638360efbdSAlfred Perlstein static const struct xdr_discrim reply_dscrm[3] = {
1648360efbdSAlfred Perlstein { (int)MSG_ACCEPTED, (xdrproc_t)xdr_accepted_reply },
1658360efbdSAlfred Perlstein { (int)MSG_DENIED, (xdrproc_t)xdr_rejected_reply },
16699064799SGarrett Wollman { __dontcare__, NULL_xdrproc_t } };
16799064799SGarrett Wollman
16899064799SGarrett Wollman /*
16999064799SGarrett Wollman * XDR a reply message
17099064799SGarrett Wollman */
17199064799SGarrett Wollman bool_t
xdr_replymsg(XDR * xdrs,struct rpc_msg * rmsg)172a7c2cd38SCraig Rodrigues xdr_replymsg(XDR *xdrs, struct rpc_msg *rmsg)
17399064799SGarrett Wollman {
174102c7c92SJohn Birrell enum msg_type *prm_direction;
175102c7c92SJohn Birrell enum reply_stat *prp_stat;
176102c7c92SJohn Birrell
1778360efbdSAlfred Perlstein assert(xdrs != NULL);
1788360efbdSAlfred Perlstein assert(rmsg != NULL);
1798360efbdSAlfred Perlstein
180102c7c92SJohn Birrell prm_direction = &rmsg->rm_direction;
181102c7c92SJohn Birrell prp_stat = &rmsg->rm_reply.rp_stat;
182102c7c92SJohn Birrell
18399064799SGarrett Wollman if (
18439f37784SPeter Wemm xdr_u_int32_t(xdrs, &(rmsg->rm_xid)) &&
185102c7c92SJohn Birrell xdr_enum(xdrs, (enum_t *) prm_direction) &&
18699064799SGarrett Wollman (rmsg->rm_direction == REPLY) )
187102c7c92SJohn Birrell return (xdr_union(xdrs, (enum_t *) prp_stat,
1888360efbdSAlfred Perlstein (caddr_t)(void *)&(rmsg->rm_reply.ru), reply_dscrm,
1898360efbdSAlfred Perlstein NULL_xdrproc_t));
19099064799SGarrett Wollman return (FALSE);
19199064799SGarrett Wollman }
19299064799SGarrett Wollman
19399064799SGarrett Wollman
19499064799SGarrett Wollman /*
19599064799SGarrett Wollman * Serializes the "static part" of a call message header.
19699064799SGarrett Wollman * The fields include: rm_xid, rm_direction, rpcvers, prog, and vers.
19799064799SGarrett Wollman * The rm_xid is not really static, but the user can easily munge on the fly.
19899064799SGarrett Wollman */
19999064799SGarrett Wollman bool_t
xdr_callhdr(XDR * xdrs,struct rpc_msg * cmsg)200a7c2cd38SCraig Rodrigues xdr_callhdr(XDR *xdrs, struct rpc_msg *cmsg)
20199064799SGarrett Wollman {
202102c7c92SJohn Birrell enum msg_type *prm_direction;
20399064799SGarrett Wollman
2048360efbdSAlfred Perlstein assert(xdrs != NULL);
2058360efbdSAlfred Perlstein assert(cmsg != NULL);
2068360efbdSAlfred Perlstein
207102c7c92SJohn Birrell prm_direction = &cmsg->rm_direction;
208102c7c92SJohn Birrell
20999064799SGarrett Wollman cmsg->rm_direction = CALL;
21099064799SGarrett Wollman cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION;
21199064799SGarrett Wollman if (
21299064799SGarrett Wollman (xdrs->x_op == XDR_ENCODE) &&
21339f37784SPeter Wemm xdr_u_int32_t(xdrs, &(cmsg->rm_xid)) &&
214102c7c92SJohn Birrell xdr_enum(xdrs, (enum_t *) prm_direction) &&
215ea21823dSPedro F. Giffuni xdr_rpcvers(xdrs, &(cmsg->rm_call.cb_rpcvers)) &&
216ea21823dSPedro F. Giffuni xdr_rpcprog(xdrs, &(cmsg->rm_call.cb_prog)) )
21739f37784SPeter Wemm return (xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_vers)));
21899064799SGarrett Wollman return (FALSE);
21999064799SGarrett Wollman }
22099064799SGarrett Wollman
22199064799SGarrett Wollman /* ************************** Client utility routine ************* */
22299064799SGarrett Wollman
22399064799SGarrett Wollman static void
accepted(enum accept_stat acpt_stat,struct rpc_err * error)224a7c2cd38SCraig Rodrigues accepted(enum accept_stat acpt_stat, struct rpc_err *error)
22599064799SGarrett Wollman {
22699064799SGarrett Wollman
2278360efbdSAlfred Perlstein assert(error != NULL);
2288360efbdSAlfred Perlstein
22999064799SGarrett Wollman switch (acpt_stat) {
23099064799SGarrett Wollman
23199064799SGarrett Wollman case PROG_UNAVAIL:
23299064799SGarrett Wollman error->re_status = RPC_PROGUNAVAIL;
23399064799SGarrett Wollman return;
23499064799SGarrett Wollman
23599064799SGarrett Wollman case PROG_MISMATCH:
23699064799SGarrett Wollman error->re_status = RPC_PROGVERSMISMATCH;
23799064799SGarrett Wollman return;
23899064799SGarrett Wollman
23999064799SGarrett Wollman case PROC_UNAVAIL:
24099064799SGarrett Wollman error->re_status = RPC_PROCUNAVAIL;
24199064799SGarrett Wollman return;
24299064799SGarrett Wollman
24399064799SGarrett Wollman case GARBAGE_ARGS:
24499064799SGarrett Wollman error->re_status = RPC_CANTDECODEARGS;
24599064799SGarrett Wollman return;
24699064799SGarrett Wollman
24799064799SGarrett Wollman case SYSTEM_ERR:
24899064799SGarrett Wollman error->re_status = RPC_SYSTEMERROR;
24999064799SGarrett Wollman return;
25099064799SGarrett Wollman
25199064799SGarrett Wollman case SUCCESS:
25299064799SGarrett Wollman error->re_status = RPC_SUCCESS;
25399064799SGarrett Wollman return;
25499064799SGarrett Wollman }
2558360efbdSAlfred Perlstein /* NOTREACHED */
25699064799SGarrett Wollman /* something's wrong, but we don't know what ... */
25799064799SGarrett Wollman error->re_status = RPC_FAILED;
2588360efbdSAlfred Perlstein error->re_lb.s1 = (int32_t)MSG_ACCEPTED;
2598360efbdSAlfred Perlstein error->re_lb.s2 = (int32_t)acpt_stat;
26099064799SGarrett Wollman }
26199064799SGarrett Wollman
26299064799SGarrett Wollman static void
rejected(enum reject_stat rjct_stat,struct rpc_err * error)263587cf682SCraig Rodrigues rejected(enum reject_stat rjct_stat, struct rpc_err *error)
26499064799SGarrett Wollman {
26599064799SGarrett Wollman
2668360efbdSAlfred Perlstein assert(error != NULL);
26799064799SGarrett Wollman
2688360efbdSAlfred Perlstein switch (rjct_stat) {
2698360efbdSAlfred Perlstein case RPC_MISMATCH:
27099064799SGarrett Wollman error->re_status = RPC_VERSMISMATCH;
27199064799SGarrett Wollman return;
27299064799SGarrett Wollman
27399064799SGarrett Wollman case AUTH_ERROR:
27499064799SGarrett Wollman error->re_status = RPC_AUTHERROR;
27599064799SGarrett Wollman return;
27699064799SGarrett Wollman }
27799064799SGarrett Wollman /* something's wrong, but we don't know what ... */
2788360efbdSAlfred Perlstein /* NOTREACHED */
27999064799SGarrett Wollman error->re_status = RPC_FAILED;
2808360efbdSAlfred Perlstein error->re_lb.s1 = (int32_t)MSG_DENIED;
2818360efbdSAlfred Perlstein error->re_lb.s2 = (int32_t)rjct_stat;
28299064799SGarrett Wollman }
28399064799SGarrett Wollman
28499064799SGarrett Wollman /*
28599064799SGarrett Wollman * given a reply message, fills in the error
28699064799SGarrett Wollman */
28799064799SGarrett Wollman void
_seterr_reply(struct rpc_msg * msg,struct rpc_err * error)288587cf682SCraig Rodrigues _seterr_reply(struct rpc_msg *msg, struct rpc_err *error)
28999064799SGarrett Wollman {
29099064799SGarrett Wollman
2918360efbdSAlfred Perlstein assert(msg != NULL);
2928360efbdSAlfred Perlstein assert(error != NULL);
2938360efbdSAlfred Perlstein
29499064799SGarrett Wollman /* optimized for normal, SUCCESSful case */
29599064799SGarrett Wollman switch (msg->rm_reply.rp_stat) {
29699064799SGarrett Wollman
29799064799SGarrett Wollman case MSG_ACCEPTED:
29899064799SGarrett Wollman if (msg->acpted_rply.ar_stat == SUCCESS) {
29999064799SGarrett Wollman error->re_status = RPC_SUCCESS;
30099064799SGarrett Wollman return;
3018360efbdSAlfred Perlstein }
30299064799SGarrett Wollman accepted(msg->acpted_rply.ar_stat, error);
30399064799SGarrett Wollman break;
30499064799SGarrett Wollman
30599064799SGarrett Wollman case MSG_DENIED:
30699064799SGarrett Wollman rejected(msg->rjcted_rply.rj_stat, error);
30799064799SGarrett Wollman break;
30899064799SGarrett Wollman
30999064799SGarrett Wollman default:
31099064799SGarrett Wollman error->re_status = RPC_FAILED;
3118360efbdSAlfred Perlstein error->re_lb.s1 = (int32_t)(msg->rm_reply.rp_stat);
31299064799SGarrett Wollman break;
31399064799SGarrett Wollman }
31499064799SGarrett Wollman switch (error->re_status) {
31599064799SGarrett Wollman
31699064799SGarrett Wollman case RPC_VERSMISMATCH:
31799064799SGarrett Wollman error->re_vers.low = msg->rjcted_rply.rj_vers.low;
31899064799SGarrett Wollman error->re_vers.high = msg->rjcted_rply.rj_vers.high;
31999064799SGarrett Wollman break;
32099064799SGarrett Wollman
32199064799SGarrett Wollman case RPC_AUTHERROR:
32299064799SGarrett Wollman error->re_why = msg->rjcted_rply.rj_why;
32399064799SGarrett Wollman break;
32499064799SGarrett Wollman
32599064799SGarrett Wollman case RPC_PROGVERSMISMATCH:
32699064799SGarrett Wollman error->re_vers.low = msg->acpted_rply.ar_vers.low;
32799064799SGarrett Wollman error->re_vers.high = msg->acpted_rply.ar_vers.high;
32899064799SGarrett Wollman break;
3298360efbdSAlfred Perlstein
3308360efbdSAlfred Perlstein case RPC_FAILED:
3318360efbdSAlfred Perlstein case RPC_SUCCESS:
3328360efbdSAlfred Perlstein case RPC_PROGNOTREGISTERED:
3338360efbdSAlfred Perlstein case RPC_PMAPFAILURE:
3348360efbdSAlfred Perlstein case RPC_UNKNOWNPROTO:
3358360efbdSAlfred Perlstein case RPC_UNKNOWNHOST:
3368360efbdSAlfred Perlstein case RPC_SYSTEMERROR:
3378360efbdSAlfred Perlstein case RPC_CANTDECODEARGS:
3388360efbdSAlfred Perlstein case RPC_PROCUNAVAIL:
3398360efbdSAlfred Perlstein case RPC_PROGUNAVAIL:
3408360efbdSAlfred Perlstein case RPC_TIMEDOUT:
3418360efbdSAlfred Perlstein case RPC_CANTRECV:
3428360efbdSAlfred Perlstein case RPC_CANTSEND:
3438360efbdSAlfred Perlstein case RPC_CANTDECODERES:
3448360efbdSAlfred Perlstein case RPC_CANTENCODEARGS:
345f12d1a5dSJames Raynard default:
346f12d1a5dSJames Raynard break;
34799064799SGarrett Wollman }
34899064799SGarrett Wollman }
349