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