Home | History | Annotate | Line # | Download | only in rpc
rpc_prot.c revision 1.3.4.1
      1 /*	$NetBSD: rpc_prot.c,v 1.3.4.1 1996/09/16 23:44:35 jtc Exp $	*/
      2 
      3 /*
      4  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
      5  * unrestricted use provided that this legend is included on all tape
      6  * media and as a part of the software program in whole or part.  Users
      7  * may copy or modify Sun RPC without charge, but are not authorized
      8  * to license or distribute it to anyone else except as part of a product or
      9  * program developed by the user.
     10  *
     11  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
     12  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
     13  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
     14  *
     15  * Sun RPC is provided with no support and without any obligation on the
     16  * part of Sun Microsystems, Inc. to assist in its use, correction,
     17  * modification or enhancement.
     18  *
     19  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
     20  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
     21  * OR ANY PART THEREOF.
     22  *
     23  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
     24  * or profits or other special, indirect and consequential damages, even if
     25  * Sun has been advised of the possibility of such damages.
     26  *
     27  * Sun Microsystems, Inc.
     28  * 2550 Garcia Avenue
     29  * Mountain View, California  94043
     30  */
     31 
     32 #if defined(LIBC_SCCS) && !defined(lint)
     33 /*static char *sccsid = "from: @(#)rpc_prot.c 1.36 87/08/11 Copyr 1984 Sun Micro";*/
     34 /*static char *sccsid = "from: @(#)rpc_prot.c	2.3 88/08/07 4.0 RPCSRC";*/
     35 static char *rcsid = "$NetBSD: rpc_prot.c,v 1.3.4.1 1996/09/16 23:44:35 jtc Exp $";
     36 #endif
     37 
     38 /*
     39  * rpc_prot.c
     40  *
     41  * Copyright (C) 1984, Sun Microsystems, Inc.
     42  *
     43  * This set of routines implements the rpc message definition,
     44  * its serializer and some common rpc utility routines.
     45  * The routines are meant for various implementations of rpc -
     46  * they are NOT for the rpc client or rpc service implementations!
     47  * Because authentication stuff is easy and is part of rpc, the opaque
     48  * routines are also in this program.
     49  */
     50 
     51 #include "namespace.h"
     52 #include <sys/param.h>
     53 #include <rpc/rpc.h>
     54 
     55 #ifdef __weak_alias
     56 __weak_alias(xdr_accepted_reply,_xdr_accepted_reply);
     57 __weak_alias(xdr_callhdr,_xdr_callhdr);
     58 __weak_alias(xdr_des_block,_xdr_des_block);
     59 __weak_alias(xdr_opaque_auth,_xdr_opaque_auth);
     60 __weak_alias(xdr_rejected_reply,_xdr_rejected_reply);
     61 __weak_alias(xdr_replymsg,_xdr_replymsg);
     62 #endif
     63 
     64 /* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */
     65 
     66 struct opaque_auth _null_auth;
     67 
     68 /*
     69  * XDR an opaque authentication struct
     70  * (see auth.h)
     71  */
     72 bool_t
     73 xdr_opaque_auth(xdrs, ap)
     74 	register XDR *xdrs;
     75 	register struct opaque_auth *ap;
     76 {
     77 
     78 	if (xdr_enum(xdrs, &(ap->oa_flavor)))
     79 		return (xdr_bytes(xdrs, &ap->oa_base,
     80 			&ap->oa_length, MAX_AUTH_BYTES));
     81 	return (FALSE);
     82 }
     83 
     84 /*
     85  * XDR a DES block
     86  */
     87 bool_t
     88 xdr_des_block(xdrs, blkp)
     89 	register XDR *xdrs;
     90 	register des_block *blkp;
     91 {
     92 	return (xdr_opaque(xdrs, (caddr_t)blkp, sizeof(des_block)));
     93 }
     94 
     95 /* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */
     96 
     97 /*
     98  * XDR the MSG_ACCEPTED part of a reply message union
     99  */
    100 bool_t
    101 xdr_accepted_reply(xdrs, ar)
    102 	register XDR *xdrs;
    103 	register struct accepted_reply *ar;
    104 {
    105 
    106 	/* personalized union, rather than calling xdr_union */
    107 	if (! xdr_opaque_auth(xdrs, &(ar->ar_verf)))
    108 		return (FALSE);
    109 	if (! xdr_enum(xdrs, (enum_t *)&(ar->ar_stat)))
    110 		return (FALSE);
    111 	switch (ar->ar_stat) {
    112 
    113 	case SUCCESS:
    114 		return ((*(ar->ar_results.proc))(xdrs, ar->ar_results.where));
    115 
    116 	case PROG_MISMATCH:
    117 		if (! xdr_u_int32_t(xdrs, &(ar->ar_vers.low)))
    118 			return (FALSE);
    119 		return (xdr_u_int32_t(xdrs, &(ar->ar_vers.high)));
    120 	}
    121 	return (TRUE);  /* TRUE => open ended set of problems */
    122 }
    123 
    124 /*
    125  * XDR the MSG_DENIED part of a reply message union
    126  */
    127 bool_t
    128 xdr_rejected_reply(xdrs, rr)
    129 	register XDR *xdrs;
    130 	register struct rejected_reply *rr;
    131 {
    132 
    133 	/* personalized union, rather than calling xdr_union */
    134 	if (! xdr_enum(xdrs, (enum_t *)&(rr->rj_stat)))
    135 		return (FALSE);
    136 	switch (rr->rj_stat) {
    137 
    138 	case RPC_MISMATCH:
    139 		if (! xdr_u_int32_t(xdrs, &(rr->rj_vers.low)))
    140 			return (FALSE);
    141 		return (xdr_u_int32_t(xdrs, &(rr->rj_vers.high)));
    142 
    143 	case AUTH_ERROR:
    144 		return (xdr_enum(xdrs, (enum_t *)&(rr->rj_why)));
    145 	}
    146 	return (FALSE);
    147 }
    148 
    149 static struct xdr_discrim reply_dscrm[3] = {
    150 	{ (int)MSG_ACCEPTED, xdr_accepted_reply },
    151 	{ (int)MSG_DENIED, xdr_rejected_reply },
    152 	{ __dontcare__, NULL_xdrproc_t } };
    153 
    154 /*
    155  * XDR a reply message
    156  */
    157 bool_t
    158 xdr_replymsg(xdrs, rmsg)
    159 	register XDR *xdrs;
    160 	register struct rpc_msg *rmsg;
    161 {
    162 	if (
    163 	    xdr_u_int32_t(xdrs, &(rmsg->rm_xid)) &&
    164 	    xdr_enum(xdrs, (enum_t *)&(rmsg->rm_direction)) &&
    165 	    (rmsg->rm_direction == REPLY) )
    166 		return (xdr_union(xdrs, (enum_t *)&(rmsg->rm_reply.rp_stat),
    167 		   (caddr_t)&(rmsg->rm_reply.ru), reply_dscrm, NULL_xdrproc_t));
    168 	return (FALSE);
    169 }
    170 
    171 
    172 /*
    173  * Serializes the "static part" of a call message header.
    174  * The fields include: rm_xid, rm_direction, rpcvers, prog, and vers.
    175  * The rm_xid is not really static, but the user can easily munge on the fly.
    176  */
    177 bool_t
    178 xdr_callhdr(xdrs, cmsg)
    179 	register XDR *xdrs;
    180 	register struct rpc_msg *cmsg;
    181 {
    182 
    183 	cmsg->rm_direction = CALL;
    184 	cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION;
    185 	if (
    186 	    (xdrs->x_op == XDR_ENCODE) &&
    187 	    xdr_u_int32_t(xdrs, &(cmsg->rm_xid)) &&
    188 	    xdr_enum(xdrs, (enum_t *)&(cmsg->rm_direction)) &&
    189 	    xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_rpcvers)) &&
    190 	    xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_prog)) )
    191 	    return (xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_vers)));
    192 	return (FALSE);
    193 }
    194 
    195 /* ************************** Client utility routine ************* */
    196 
    197 static void
    198 accepted(acpt_stat, error)
    199 	register enum accept_stat acpt_stat;
    200 	register struct rpc_err *error;
    201 {
    202 
    203 	switch (acpt_stat) {
    204 
    205 	case PROG_UNAVAIL:
    206 		error->re_status = RPC_PROGUNAVAIL;
    207 		return;
    208 
    209 	case PROG_MISMATCH:
    210 		error->re_status = RPC_PROGVERSMISMATCH;
    211 		return;
    212 
    213 	case PROC_UNAVAIL:
    214 		error->re_status = RPC_PROCUNAVAIL;
    215 		return;
    216 
    217 	case GARBAGE_ARGS:
    218 		error->re_status = RPC_CANTDECODEARGS;
    219 		return;
    220 
    221 	case SYSTEM_ERR:
    222 		error->re_status = RPC_SYSTEMERROR;
    223 		return;
    224 
    225 	case SUCCESS:
    226 		error->re_status = RPC_SUCCESS;
    227 		return;
    228 	}
    229 	/* something's wrong, but we don't know what ... */
    230 	error->re_status = RPC_FAILED;
    231 	error->re_lb.s1 = (long)MSG_ACCEPTED;
    232 	error->re_lb.s2 = (long)acpt_stat;
    233 }
    234 
    235 static void
    236 rejected(rjct_stat, error)
    237 	register enum reject_stat rjct_stat;
    238 	register struct rpc_err *error;
    239 {
    240 
    241 	switch (rjct_stat) {
    242 
    243 	case RPC_VERSMISMATCH:
    244 		error->re_status = RPC_VERSMISMATCH;
    245 		return;
    246 
    247 	case AUTH_ERROR:
    248 		error->re_status = RPC_AUTHERROR;
    249 		return;
    250 	}
    251 	/* something's wrong, but we don't know what ... */
    252 	error->re_status = RPC_FAILED;
    253 	error->re_lb.s1 = (long)MSG_DENIED;
    254 	error->re_lb.s2 = (long)rjct_stat;
    255 }
    256 
    257 /*
    258  * given a reply message, fills in the error
    259  */
    260 void
    261 _seterr_reply(msg, error)
    262 	register struct rpc_msg *msg;
    263 	register struct rpc_err *error;
    264 {
    265 
    266 	/* optimized for normal, SUCCESSful case */
    267 	switch (msg->rm_reply.rp_stat) {
    268 
    269 	case MSG_ACCEPTED:
    270 		if (msg->acpted_rply.ar_stat == SUCCESS) {
    271 			error->re_status = RPC_SUCCESS;
    272 			return;
    273 		};
    274 		accepted(msg->acpted_rply.ar_stat, error);
    275 		break;
    276 
    277 	case MSG_DENIED:
    278 		rejected(msg->rjcted_rply.rj_stat, error);
    279 		break;
    280 
    281 	default:
    282 		error->re_status = RPC_FAILED;
    283 		error->re_lb.s1 = (long)(msg->rm_reply.rp_stat);
    284 		break;
    285 	}
    286 	switch (error->re_status) {
    287 
    288 	case RPC_VERSMISMATCH:
    289 		error->re_vers.low = msg->rjcted_rply.rj_vers.low;
    290 		error->re_vers.high = msg->rjcted_rply.rj_vers.high;
    291 		break;
    292 
    293 	case RPC_AUTHERROR:
    294 		error->re_why = msg->rjcted_rply.rj_why;
    295 		break;
    296 
    297 	case RPC_PROGVERSMISMATCH:
    298 		error->re_vers.low = msg->acpted_rply.ar_vers.low;
    299 		error->re_vers.high = msg->acpted_rply.ar_vers.high;
    300 		break;
    301 	}
    302 }
    303