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