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