Back to index

glibc  2.9
rpc_prot.c
Go to the documentation of this file.
00001 /* @(#)rpc_prot.c    2.3 88/08/07 4.0 RPCSRC */
00002 /*
00003  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
00004  * unrestricted use provided that this legend is included on all tape
00005  * media and as a part of the software program in whole or part.  Users
00006  * may copy or modify Sun RPC without charge, but are not authorized
00007  * to license or distribute it to anyone else except as part of a product or
00008  * program developed by the user.
00009  *
00010  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
00011  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
00012  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
00013  *
00014  * Sun RPC is provided with no support and without any obligation on the
00015  * part of Sun Microsystems, Inc. to assist in its use, correction,
00016  * modification or enhancement.
00017  *
00018  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
00019  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
00020  * OR ANY PART THEREOF.
00021  *
00022  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
00023  * or profits or other special, indirect and consequential damages, even if
00024  * Sun has been advised of the possibility of such damages.
00025  *
00026  * Sun Microsystems, Inc.
00027  * 2550 Garcia Avenue
00028  * Mountain View, California  94043
00029  */
00030 #if !defined(lint) && defined(SCCSIDS)
00031 static char sccsid[] = "@(#)rpc_prot.c 1.36 87/08/11 Copyr 1984 Sun Micro";
00032 #endif
00033 
00034 /*
00035  * rpc_prot.c
00036  *
00037  * Copyright (C) 1984, Sun Microsystems, Inc.
00038  *
00039  * This set of routines implements the rpc message definition,
00040  * its serializer and some common rpc utility routines.
00041  * The routines are meant for various implementations of rpc -
00042  * they are NOT for the rpc client or rpc service implementations!
00043  * Because authentication stuff is easy and is part of rpc, the opaque
00044  * routines are also in this program.
00045  */
00046 
00047 #include <sys/param.h>
00048 
00049 #include <rpc/rpc.h>
00050 
00051 /* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */
00052 
00053 /*
00054  * XDR an opaque authentication struct
00055  * (see auth.h)
00056  */
00057 bool_t
00058 xdr_opaque_auth (XDR *xdrs, struct opaque_auth *ap)
00059 {
00060 
00061   if (INTUSE(xdr_enum) (xdrs, &(ap->oa_flavor)))
00062     return INTUSE(xdr_bytes) (xdrs, &ap->oa_base,
00063                     &ap->oa_length, MAX_AUTH_BYTES);
00064   return FALSE;
00065 }
00066 INTDEF(xdr_opaque_auth)
00067 
00068 /*
00069  * XDR a DES block
00070  */
00071 bool_t
00072 xdr_des_block (XDR *xdrs, des_block *blkp)
00073 {
00074   return INTUSE(xdr_opaque) (xdrs, (caddr_t) blkp, sizeof (des_block));
00075 }
00076 INTDEF(xdr_des_block)
00077 
00078 /* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */
00079 
00080 /*
00081  * XDR the MSG_ACCEPTED part of a reply message union
00082  */
00083 bool_t
00084 xdr_accepted_reply (XDR *xdrs, struct accepted_reply *ar)
00085 {
00086   /* personalized union, rather than calling xdr_union */
00087   if (!INTUSE(xdr_opaque_auth) (xdrs, &(ar->ar_verf)))
00088     return FALSE;
00089   if (!INTUSE(xdr_enum) (xdrs, (enum_t *) & (ar->ar_stat)))
00090     return FALSE;
00091   switch (ar->ar_stat)
00092     {
00093     case SUCCESS:
00094       return ((*(ar->ar_results.proc)) (xdrs, ar->ar_results.where));
00095     case PROG_MISMATCH:
00096       if (!INTUSE(xdr_u_long) (xdrs, &(ar->ar_vers.low)))
00097        return FALSE;
00098       return (INTUSE(xdr_u_long) (xdrs, &(ar->ar_vers.high)));
00099     default:
00100       return TRUE;
00101     }
00102   return TRUE;              /* TRUE => open ended set of problems */
00103 }
00104 INTDEF(xdr_accepted_reply)
00105 
00106 /*
00107  * XDR the MSG_DENIED part of a reply message union
00108  */
00109 bool_t
00110 xdr_rejected_reply (XDR *xdrs, struct rejected_reply *rr)
00111 {
00112   /* personalized union, rather than calling xdr_union */
00113   if (!INTUSE(xdr_enum) (xdrs, (enum_t *) & (rr->rj_stat)))
00114     return FALSE;
00115   switch (rr->rj_stat)
00116     {
00117     case RPC_MISMATCH:
00118       if (!INTUSE(xdr_u_long) (xdrs, &(rr->rj_vers.low)))
00119        return FALSE;
00120       return INTUSE(xdr_u_long) (xdrs, &(rr->rj_vers.high));
00121 
00122     case AUTH_ERROR:
00123       return INTUSE(xdr_enum) (xdrs, (enum_t *) & (rr->rj_why));
00124     }
00125   return FALSE;
00126 }
00127 INTDEF(xdr_rejected_reply)
00128 
00129 static const struct xdr_discrim reply_dscrm[3] =
00130 {
00131   {(int) MSG_ACCEPTED, (xdrproc_t) INTUSE(xdr_accepted_reply)},
00132   {(int) MSG_DENIED, (xdrproc_t) INTUSE(xdr_rejected_reply)},
00133   {__dontcare__, NULL_xdrproc_t}};
00134 
00135 /*
00136  * XDR a reply message
00137  */
00138 bool_t
00139 xdr_replymsg (xdrs, rmsg)
00140      XDR *xdrs;
00141      struct rpc_msg *rmsg;
00142 {
00143   if (INTUSE(xdr_u_long) (xdrs, &(rmsg->rm_xid)) &&
00144       INTUSE(xdr_enum) (xdrs, (enum_t *) & (rmsg->rm_direction)) &&
00145       (rmsg->rm_direction == REPLY))
00146     return INTUSE(xdr_union) (xdrs, (enum_t *) & (rmsg->rm_reply.rp_stat),
00147                            (caddr_t) & (rmsg->rm_reply.ru), reply_dscrm,
00148                            NULL_xdrproc_t);
00149   return FALSE;
00150 }
00151 INTDEF(xdr_replymsg)
00152 
00153 
00154 /*
00155  * Serializes the "static part" of a call message header.
00156  * The fields include: rm_xid, rm_direction, rpcvers, prog, and vers.
00157  * The rm_xid is not really static, but the user can easily munge on the fly.
00158  */
00159 bool_t
00160 xdr_callhdr (xdrs, cmsg)
00161      XDR *xdrs;
00162      struct rpc_msg *cmsg;
00163 {
00164 
00165   cmsg->rm_direction = CALL;
00166   cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION;
00167   if (
00168        (xdrs->x_op == XDR_ENCODE) &&
00169        INTUSE(xdr_u_long) (xdrs, &(cmsg->rm_xid)) &&
00170        INTUSE(xdr_enum) (xdrs, (enum_t *) & (cmsg->rm_direction)) &&
00171        INTUSE(xdr_u_long) (xdrs, &(cmsg->rm_call.cb_rpcvers)) &&
00172        INTUSE(xdr_u_long) (xdrs, &(cmsg->rm_call.cb_prog)))
00173     return INTUSE(xdr_u_long) (xdrs, &(cmsg->rm_call.cb_vers));
00174   return FALSE;
00175 }
00176 INTDEF(xdr_callhdr)
00177 
00178 /* ************************** Client utility routine ************* */
00179 
00180 static void
00181 accepted (enum accept_stat acpt_stat,
00182          struct rpc_err *error)
00183 {
00184   switch (acpt_stat)
00185     {
00186 
00187     case PROG_UNAVAIL:
00188       error->re_status = RPC_PROGUNAVAIL;
00189       return;
00190 
00191     case PROG_MISMATCH:
00192       error->re_status = RPC_PROGVERSMISMATCH;
00193       return;
00194 
00195     case PROC_UNAVAIL:
00196       error->re_status = RPC_PROCUNAVAIL;
00197       return;
00198 
00199     case GARBAGE_ARGS:
00200       error->re_status = RPC_CANTDECODEARGS;
00201       return;
00202 
00203     case SYSTEM_ERR:
00204       error->re_status = RPC_SYSTEMERROR;
00205       return;
00206 
00207     case SUCCESS:
00208       error->re_status = RPC_SUCCESS;
00209       return;
00210     }
00211   /* something's wrong, but we don't know what ... */
00212   error->re_status = RPC_FAILED;
00213   error->re_lb.s1 = (long) MSG_ACCEPTED;
00214   error->re_lb.s2 = (long) acpt_stat;
00215 }
00216 
00217 static void
00218 rejected (enum reject_stat rjct_stat,
00219          struct rpc_err *error)
00220 {
00221   switch (rjct_stat)
00222     {
00223     case RPC_VERSMISMATCH:
00224       error->re_status = RPC_VERSMISMATCH;
00225       return;
00226     case AUTH_ERROR:
00227       error->re_status = RPC_AUTHERROR;
00228       return;
00229     default:
00230       /* something's wrong, but we don't know what ... */
00231       error->re_status = RPC_FAILED;
00232       error->re_lb.s1 = (long) MSG_DENIED;
00233       error->re_lb.s2 = (long) rjct_stat;
00234       return;
00235     }
00236 }
00237 
00238 /*
00239  * given a reply message, fills in the error
00240  */
00241 void
00242 _seterr_reply (struct rpc_msg *msg,
00243               struct rpc_err *error)
00244 {
00245   /* optimized for normal, SUCCESSful case */
00246   switch (msg->rm_reply.rp_stat)
00247     {
00248     case MSG_ACCEPTED:
00249       if (msg->acpted_rply.ar_stat == SUCCESS)
00250        {
00251          error->re_status = RPC_SUCCESS;
00252          return;
00253        };
00254       accepted (msg->acpted_rply.ar_stat, error);
00255       break;
00256 
00257     case MSG_DENIED:
00258       rejected (msg->rjcted_rply.rj_stat, error);
00259       break;
00260 
00261     default:
00262       error->re_status = RPC_FAILED;
00263       error->re_lb.s1 = (long) (msg->rm_reply.rp_stat);
00264       break;
00265     }
00266   switch (error->re_status)
00267     {
00268 
00269     case RPC_VERSMISMATCH:
00270       error->re_vers.low = msg->rjcted_rply.rj_vers.low;
00271       error->re_vers.high = msg->rjcted_rply.rj_vers.high;
00272       break;
00273 
00274     case RPC_AUTHERROR:
00275       error->re_why = msg->rjcted_rply.rj_why;
00276       break;
00277 
00278     case RPC_PROGVERSMISMATCH:
00279       error->re_vers.low = msg->acpted_rply.ar_vers.low;
00280       error->re_vers.high = msg->acpted_rply.ar_vers.high;
00281       break;
00282     default:
00283       break;
00284     }
00285 }
00286 libc_hidden_def (_seterr_reply)